- 线程池执行流程
-
线程池的状态
- RUNNING
- SHUTDOWN
- STOP
- TIDYING
- TERMINATED
-
线程池优雅关闭
线程池有两个关闭方法,shutdown()
和shutdownNow()
,shutdown()
切换到SHUTDOWN状态,shutdownNow()
切换到STOP状态,当队列和线程池都为空的时候切换到TIDYING状态,最后执行terminated()
进入到TERMINATED状态。
关闭线程池的时候,调用`shutdown()`和`shutdownNow()`线程池不会立即关闭。如果需要在线程池关闭之后做资源回收处理等,可以
调用`awaitTermination()`来等待线程池关闭;`awaitTermination()`会不断循环判断线程池是否达到了最终状态TERMAINATED。
如果是就返回,如果不是就通过 termination 条件变量阻塞一段时间,之后继续判断。
shutdown()不会清空任务队列,会等所有任务执行完成,只会中断空闲的线程;shutdownNow()会中断所有线程,清空任务队列。
// executor.shutdownNow();
executor.shutdown(); // 关闭线程池
// 如果希望在线程池彻底关闭之后进行其他操作比如资源的回收等,可以:
try {
boolean flag = true;
do {
flag = !executor.awaitTermination(500, TimeUnit.MILLISECONDS);
} while (flag);
} catch (InterruptedException e) {
// 异常处理
}
线程池状态之间的迁移过程
-
线程池的拒绝策略
- CallerRunsPolicy:调用者直接在自己线程里执行,线程池不处理;
- AbortPolicy:线程池抛异常。默认拒绝策略;
- DiscardPolicy:线程池直接丢掉任务;
- DiscardOldestPolicy:删除队列中最早的任务,将当前任务入列;
-
corePoolSize和maxPoolSize一般设置为多大
-
CPU密集型
CPU密集型就是指该任务需要大量计算而没有阻塞,CPU一直全速运行;CPU密集型只有在真正的多核CPU上才能得到加速(通过多线程)。CPU密集型任务配置尽可能少的线程数。
CPU密集型线程数配置公式:CPU核数 + 1
-
I/O密集型
IO密集型指该任务需要大量的IO,即大量的阻塞。在单线程上运行IO密集型的任务会导致大量的CPU运算能力浪费在等待上。所以IO密集型任务中使用多线程可以大大加速程序运行。即使在单核CPU上,这种加速主要利用了被浪费掉的阻塞时间。
由于IO密集型任务的线程并不是一直在执行任务,大部分线程都在阻塞,所以应配置尽可能多的线程
-
配置方式一;
IO密集型线程数配置公式一:CPU核数 * 2
-
配置方式二
IO密集型线程数配置公式二:CPU核数 / (1 - 阻塞系数) (阻塞系数在0.8到0.9之间)
比如:8核 / (1 - 0.9) = 80个线程
线程数量只增加不减少也不行。当负载降低时,可减少线程数量,如果一个线程空闲时间达到 keepAliveTime,该线程就退出。默认情况下线程池最少会保持 corePoolSize 个线程。
maxPoolSize 最大线程数在生产环境上往往设置成corePoolSize一样,减少在处理过程中创建线程的开销。
-
-