java中线程池怎么使用?

问题背景

线程池是一个经常用到的东西,在各类面试过程也会被问及,简单梳理一波,查漏补缺。

一、什么是线程池?

线程池(Thread Pool)是一种基于池化思想管理线程的工具,经常出现在多线程服务器中,如MySQL,用来创建和管理线程。

二、为什么要使用线程池?

(1)线程比较多时,创建销毁线程的开销、调度线程的开销等就会比较大,降低了计算机的整体性能。
(2)线程池维护和管理多个线程。这种做法,一方面避免了处理任务时创建销毁线程开销的代价,缩短了对任务的响应时间,另一方面避免了线程数量膨胀导致的过分调度问题,保证了对内核的充分利用

三、怎么创建一个线程池?

我们可以通过ThreadPoolExecutor来创建一个线程池。它有四个重载方法,但是最终都会调用最后一个构造方法:
image.png
直接查看第四个构造方法:
image.png
各参数的意义如下:
corePoolSize:线程池长期维持的线程数,即使线程处于Idle状态,也不会回收。
maximumPoolSize:线程数的上限
keepAliveTime:空闲的时间,超过这个空闲时间,线程将被回收
unit:空闲时间的时间单位
workQueue:任务的排队队列,当线程都运行的时候,有空的线程将从队列汇总进行拿取
threadFactroy:当核心线程小于满线程的时候,又需要多加线程,则需要从工厂中获取线程
handler:拒绝策略,当线程过多的时候的策略
基于这个方法,java提供了4种常见的线程池:
newCachedThreadPool 创建一个可缓存线程池程
newFixedThreadPool 创建一个定长线程池
newScheduledThreadPool 创建一个定长线程池
newSingleThreadExecutor 创建一个单线程化的线程池

四、线程池针对于任务的执行顺序是怎样的呢?

(1)任务过来之后,看看corePoolSize是否有空闲的,空闲的话就执行。不然就放入任务队列。然后任务队列会通知线程工厂,需要new几个线程来执行。
(2)当任务队列的queue满了的时候,再提交任务,就要触发拒绝策略。,就执行拒绝策略,拒绝执行。

五、拒绝策略有哪些?

如果是想实现自定义的策略,可以实现RejectedExecutionHandler 接口。
线程池提供了如下的几种策略供选择。
image.png![拒绝策略](vx_images/272114023247009.png =662x)
AbortPolicy:默认策略,抛出RejectedExecutionException
DiscardPolicy:忽略当前提交的任务
DiscardOldestPolicy:丢弃任务队列中最老的任务,给新任务腾出地方
CallerRunsPolicy:由提交任务者执行这个任务