这是我参与「第四届青训营 」笔记创作活动的的第4天
Java异步线程池| 青训营笔记
线程池实现异步消息推送
执行器:Executor
方案一:使用静态工厂方法
newCachedThreadPool:如果有新的请求,就新建一个新的线程,闲置线程在60s后被清空,
newFixedThreadPool:构建大小固定的线程池,多出的线程会放在队列中,
newSingleThreadExecutor:大小为1,执行任务一个接着一个,
这三个方法返回ExecutorService接口的ThreadPoolExecutor对象。
方案二:自定义线程池对象(最终使用)
自定义executor相关的config类
@Configuration
@EnableAsync
@Slf4j
public class ExecutorConfig {
//Spring线程池
@Bean("WeiXinMsgExecutor")
public Executor WeiXinMsgExecutor(){
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
//核心线程数,设置为当前机器线程数
threadPoolTaskExecutor.setCorePoolSize(Runtime.getRuntime().availableProcessors()+1);
//设置最大线程数,设置为核心数*2
threadPoolTaskExecutor.setMaxPoolSize(threadPoolTaskExecutor.getPoolSize() * 2);
//设置WorkQueue大小,设置为Integer包装类最大值
threadPoolTaskExecutor.setQueueCapacity(Integer.MAX_VALUE);
//设置线程中的线程名前缀
threadPoolTaskExecutor.setThreadNamePrefix("sjsb-");
//拒绝策略
threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
//线程池初始化
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
}
改进:使用配置文件实现手动切换线程限制
拒绝策略
rejectedExectutionHandler参数字段用于配置绝策略,常用拒绝策略如下
- AbortPolicy:用于被拒绝任务的处理程序,它将抛出RejectedExecutionException
- CallerRunsPolicy:用于被拒绝任务的处理程序,它直接在execute方法的调用线程中运行被拒绝的任务。
- DiscardOldestPolicy:用于被拒绝任务的处理程序,它放弃最旧的未处理请求,然后重试execute。
- DiscardPolicy:用于被拒绝任务的处理程序,默认情况下它将丢弃被拒绝的任务。
线程池业务:参考美团
线程池参数设定
方案一:经验主义
CPU 密集型:CorePoolSize=服务器核心线程数+1;CoreMaxPoolSize=COrePoolSize*2;
当计算(CPU)密集型的线程偶尔由于页缺失故障或者其他原因而暂停时,这个“额外”的线程也能确保 CPU 的时钟周期不会被浪费。
方案二:动态设置参数,参考:如何设置线程池参数?美团给出了一个让面试官虎躯一震的回答。 (qq.com),Java线程池实现原理及其在美团业务中的实践 (qq.com) 下一次来实验。
方案三:(采用),多次实验得出最佳参数
\