keepAliveTime为0以及队列太小导致ThreadPoolExecutor不断创建新线程
本文产生原因
群友问题:
使用ThreadPoolExecutor实现固定大小的线程池,但是程序跑一段时间后,就会重新创建新的线程,求问有人遇到过这个问题吗?
询问工作队列,最大线程数,超时时间参数值设置
猜测
队列太小。容易导致队列满后,启动非核心线程。怀疑 keepAliveTime为0,导致线程池的线程runWorker期间,调用getTask不等待。
线程池
new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, timeUnit, workQueue,Executors.defaultThreadFactory(), defaultHandler);
execute提交任务时:
当execute时,线程小于corePoolSize,则addWorker(firstTask,true)创建新线程。
当线程数量 大于核心数量corePoolSize后,则将任务入队。
当workQueue到达最大数量时,继续创建线程直到线程数量大于maximumPoolSize
当线程数量大于maximumPoolSize后,执行拒绝策略defaultHandler
TERMINALTED:当非core线程空闲时间(getTask)超过keepAliveTime, timeUnit指定的时间后,则退出。
threadPoolExecutor允许核心线程退出,类似于5.
线程池中的线程何时死亡?
源码
查看源码,【keepAliveTime为0,会在队列为空的时候不等待】,返回0.(这里是ArrayBlockingQueue的实现)
测试
jvisualVM 查看线程
现象:能看见在不断创建线程。应该有一个核心线程,但所有线程的name都在变化。
结论:
- keepAliveTime为0以及队列太小导致ThreadPoolExecutor不断创建新线程
- 核心线程并不指的最先创建的那几个。 而是指当前少于core线程就算核心线程。
- keepAliveTime为0导致非core线程运行完后就休眠。查看ThreadPoolExecutor#getTask