一、线程池的优点
-
减少资源创建 => 减少内存开销,创建线程占用内存
-
降低系统开销 => 创建线程需要时间,会延迟处理的请求
-
提高稳定稳定性 => 避免无限创建线程引起的 OutOfMemoryError
二、线程池参数
- 核心线程数 corePoolSize
- 最大线程数 maxPoolSize
- 缓冲队列 queueCapacity
- 可空闲时间 keepAliveSeconds
- 拒绝策略 rejectedExecutionHandler
- 异步线程前缀 threadNamePrefix
- 时间单位 unit
代码举例
/**
* 计算的线程池
*
* @return
*/
@Bean("calculateExecutor")
public Executor calculateExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
/** 核心线程数20:线程池创建时候初始化的线程数 **/
executor.setCorePoolSize(20);
/** 最大线程数200:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程 **/
executor.setMaxPoolSize(50);
/** 缓冲队列200:用来缓冲执行任务的队列 **/
executor.setQueueCapacity(2000);
/**允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁 **/
executor.setKeepAliveSeconds(60);
/**异步线程前缀**/
executor.setThreadNamePrefix("calculateExecutor-");
/**直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务**/
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
三、线程池工作流程
-
判断核心线程数是否已满,核心线程数大小和 corePoolSize 参数有关,未满则创建线程执行任务
-
若核心线程池已满,判断队列是否满,队列是否满和 workQueue 参数有关,若未满则加入队列中
-
若队列已满,判断线程池是否已满,线程池是否已满和 maximumPoolSize 参数有关,若未满创建线程执行任务
-
若线程池已满,则采用拒绝策略处理无法执执行的任务,拒绝策略和 handler 参数有关
四、ExecutorService 中的四种线程池
- 创建可缓存的线程池
ExecutorService executor=Executors.newCachedThreadPool (n)
如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
- 创建单线程的线程池
ExecutorService executor=Executors.newSingleThreadExecutor()
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
- 创建固定长度的线程池
ExecutorService executor=ecutors.newFixedThreadPool(n)
- 创建定时线程池
ExecutorService executor=newScheduledThreadPool(n)
创建一个定长线程池,支持定时及周期性任务执行。
ExecutorService executor=newScheduledThreadPool(1);
executor.scheduleAtFixedRate(() -> {
try{
...// 线程任务处理
}catch (Exception e){
e.printStackTrace();
}
}, 0, 10, TimeUnit.SECONDS);
注意:
1、ScheduledExecutorService 遇到异常后续任务不继续执行,需要加 try cache 防止任务终止
2、定时线程分两种
- scheduleAtFixedRate(commod,initialDelay,period,unit)
系统启动后按照固定频率来执行 - scheduleWithFixedDelay(commod,initialDelay,delay,unit)
上一个任务执行完 delay 一定时间后开始执行下一个任务
五、线程池的拒绝策略
- 直接丢弃(DiscardPolicy)
- 丢弃队列中最老的任务(DiscardOldestPolicy)
- 抛异常(AbortPolicy)
- 将任务分给调用线程来执行(CallerRunsPolicy)
六、禁用 Executors 创建线程池
亲自踩过坑,Executors 创建线程池中 FixedThreadPool 和 SingleThreadExecutor 允许的请求队列长度 Integer.MAX_VALUE,当任务太多时会在任务队列堆积大量的请求,从而引起 OOM 异常;CachedThreadPool 允许创建的线程数为 Integer.MAX_VALUE,当任务太多时会创建太多的线程数,从而引起 OOM 异常。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于