线程池
Executors.newCachedThreadPool();
Executors.newFixedThreadPool(10);
Executors.newSingleThreadExecutor();
查源码,都是new 的一个线程池类 ThreadPoolExecutor,只是参数不同;
ThreadPoolExecutor
参数
ThreadPoolExecutor 的参数有6个:
corePoolSize 、 maximumPoolSize 、 keepAliveTime 、 workQueue
threadFactory 、 handler ;
非核心参数:
-
ThreadFactory threadFactory,制造线程的工厂
-
RejectedExecutionHandler handler,线程超过线程池的最大处理量时,抛出拒绝执行异常
核心参数
-
corePoolSize,一直存活的核心线程数,
-
maximumPoolSize,最大线程数,线程池最大容量
-
keepAliveTime,超过corePoolSize数量的空闲线程可存活时间,超过这个时间的线程对象会被销毁
-
workQueue,一个阻塞队列,用例存放任务,等待线程执行
线程池执行流程
假设现在有如下一个线程池
线程任务执行流程如下:
-
先来的任务 T1 ... T10 会直接被 core thread 的 ct1 ... ct10 执行
-
继续来的任务 T11 ... T20 会被放进 work queue中,因为队列的size=10,就刚好存放 10个任务( core thread 的 ct1 ... ct10 还在执行 T1 ... T10)
-
继续来的任务 T21 ... T30 ,线程池会创建其他线程对象 other thread(最多10个,因为线程池的最大线程数为20)的 ot1 ... ot10 来执行
-
如果仍有任务进来 T31... ,此时会报异常,线程池已经不能再执行和保存任务了,后续来的任务都不会执行(RejectedExecutionHandler 处理),因为线程池的最大容量= maximumPoolSize + workQueue = 30
-
如果有任务执行完成(ct1 ... ct10执行的 T1 ...T10,ot1 ... ot10执行的 T21 ... T31),空闲的线程就会去执行 workQueue中的任务
-
如果workQueue中的任务也执行完成, 没有其他任务进来,空闲的线程存活 10S(keepAliveTime)后会被销毁(core thread 和 other thread 都有可能被销毁),直到线程池中存活的线程=10个(corePoolSize)
Executors 的三个线程池
newCachedThreadPool()
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
源码可见
-
核心线程数是 0
-
最大线程数是 无穷大
-
空闲线程存活 60S
-
阻塞队列 SynchronousQueue,看源码可知,size = 0
所以 newCachedThreadPool 是一个初始线程数为0,线程数随着任务增加而增加,没有阻塞队列存放任务,空闲线程存活60S的线程池
newFixedThreadPool()
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
源码可见
-
核心线程数是传入的参数 nThreads
-
最大线程数是传入的参数 nThreads
-
空闲线程存活时间是 0s(corePoolSize=maximumPoolSize,也不会有其他线程进入,线程池的线程数一直都是 nThreads)
-
阻塞列队 LinkedBlockingQueue,是一个链表,size不限
所以 newFixedThreadPool 是一个 初始线程数和最大线程数都为 nThreads,阻塞队列可存放无限多任务,无需要销毁的空闲线程的线程池
newSingleThreadExecutor()
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
newSingleThreadExecutor 就是只有 一个线程的线程池(特殊的newFixedThreadPool )