深入系统底层剖析为什么需要线程池
线程池Exceutor框架解析
线程池实现原理剖析
线程池执行流程源码解读
如何合理配置线程池的大小
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
- corePoolSize:线程池保有的最小线程数。
- maximumPoolSize:线程池创建的最大线程数。
- keepAliveTime:上面提到项目根据忙闲来增减人员,那在编程世界里,如何定义忙和闲呢?很简单,一个线程如果在一段时间内,都没有执行任务,说明很闲,keepAliveTime 和 unit 就是用来定义这个“一段时间”的参数。也就是说,如果一个线程空闲了keepAliveTime & unit这么久,而且线程池的线程数大于 corePoolSize ,那么这个空闲的线程就要被回收了。
- unit:keepAliveTime 的时间单位
- workQueue:任务队列
- threadFactory:线程工厂对象,可以自定义如何创建线程,如给线程指定name。
- handler:自定义任务的拒绝策略。线程池中所有线程都在忙碌,且任务队列已满,线程池就会拒绝接收再提交的任务。handler 就是拒绝策略,包括 4 种(即RejectedExecutionHandler 接口的 4个实现类)。
a. AbortPolicy:默认的拒绝策略,直接抛出异常,throws RejectedExecutionException
b. CallerRunsPolicy:关闭当前业务,如果被丢弃的线程任务为关闭,则执行改下次的任务。提交任务的线程自己去执行该任务
c. DiscardPolicy:直接丢弃任务,不抛出任何异常
d. DiscardOldestPolicy:丢弃最老的任务,加入新的任务
e. 自定义拒绝策略。
ThreadPoolExecutor THREAD_POOL_EXECUTOR =
new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors() * 2,
Runtime.getRuntime().availableProcessors() * 2,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(200),
new ThreadFactoryBuilder().setNameFormat("EXPORT-EXCEL_THREAD-POOL-%d").build());
corePoolSize: Runtime.getRuntime().availableProcessors() * 2 (获取核心CPU数*2)
maximumPoolSize:Runtime.getRuntime().availableProcessors() * 2 (获取核心CPU数*2)
keepAliveTime:0
workQueue:LinkedBlockingQueue(200)
LinkedBlockingQueue\不指定容量,默认为Integer.MAX_VALUE,也就是无界队列。所以为了避免队列过大造成机器负载或者内存爆满的情况出现,我们在使用的时候建议手动传一个队列的大小。
threadFactory: ThreadFactoryBuilder().setNameFormat("EXPORT-EXCEL_THREAD-POOL-%d").build()
- 线程池是什么时候创建线程的?
- 任务提交的时候
_
- 任务runnable task是先放到core到maxThread之间的线程,还是先放到队列?
- 先放队列!!!
_
队列中的任务是什么时候取出来的?
- worker中 runWorker() 一个任务完成后,会取下一个任务
什么时候会触发reject策略?
- 队列满并且maxthread也满了, 还有新任务,默认策略是reject
core到maxThread之间的线程什么时候会die?
- 没有任务时,或者抛异常时。
- core线程也会die的,core到maxThread之间的线程有可能会晋升到core线程区间,
- core max只是个计数,线程并不是创建后就固定在一个区间了
task抛出异常,线程池中这个work thread还能运行其他任务吗?
- 不能。 但是会创建新的线程, 新线程可以运行其他task。
- 对于 schedulerThreadPoolExecutor? 虽然有新线程,但是旧的循环任务不会再继续执行了, 开发实践推荐任务中捕获所有Exception