在springboot中使用 ThreadPoolTaskExecutor 线程池,如果核心线程数 、最大线程数或者等待队列设置的不合理,或者线程入线程池的速度大于消化线程的速度,会出现异常。这种情况在实际生产环境中遇到过,因为配置不合理,会导致程序卡死或者请求数据丢失。
解决的思路是重写线程池拒绝策略,将拒绝的线程存入内存中,自己做维护。部分代码如下:
/**
* @Description: 线程池自定义拒绝策略
* @Author: liumeng
* @Date: 2018/12/26 11:25
**/
public class MyRejectedPolicyHandler implements RejectedExecutionHandler {
/**
* @Description: 将拒绝的线程放到全局变量中
* @Author: liumeng
* @Date: 2018/12/26 11:25
* @Param: [r, executor]
* @Return: void
**/
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
//维护这个类
FutureTask task = (FutureTask)r;
// 可以将其维护在内存的一个线程安全队列中
//做告警处理
}
}
然后配置线程池拒绝策略
@Bean
public Executor asyncServiceExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(10);
//配置最大线程数
executor.setMaxPoolSize(1000);
//配置队列最大长度
executor.setQueueCapacity(1000);
// 自定义拒绝策略
executor.setRejectedExecutionHandler(new MyRejectedPolicyHandler());
executor.initialize();
return executor;
}
流转简单原理如下图:
之后,可以通过AOP方式,在执行线程方法之前,先检验内存的队列中有无拒绝的Task,若有,则先执行此Task
@Resource
private Executor asyncServiceExecutor;
// 判断 告警等。
// 执行
asyncServiceExecutor.execute(it.next());