Java异步线程池| 青训营笔记

265 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的的第4天

Java异步线程池| 青训营笔记

线程池实现异步消息推送

执行器:Executor

image-20220810205747762

方案一:使用静态工厂方法

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:用于被拒绝任务的处理程序,默认情况下它将丢弃被拒绝的任务。

线程池业务:参考美团

image-20220810202146995

线程池参数设定

方案一:经验主义

CPU 密集型:CorePoolSize=服务器核心线程数+1;CoreMaxPoolSize=COrePoolSize*2;

当计算(CPU)密集型的线程偶尔由于页缺失故障或者其他原因而暂停时,这个“额外”的线程也能确保 CPU 的时钟周期不会被浪费。

image-20220810211456682

方案二:动态设置参数,参考:如何设置线程池参数?美团给出了一个让面试官虎躯一震的回答。 (qq.com)Java线程池实现原理及其在美团业务中的实践 (qq.com) 下一次来实验。

方案三:(采用),多次实验得出最佳参数

\