总共有四种拒绝策略,实际线程数量超过线程池设定的数量,将会启用拒绝策略
1. AbortPolicy(默认拒绝策略): 实际线程数量大于维护队列中设定的数量,将会触发拒绝任务的处理程序,它将抛出RejectedExecutionException
2. DiscardPolicy: 实际线程数量大于维护队列中设定的数量,将会被静默丢弃
3. DiscardOldestPolicy: 实际线程数量大于维护队列中设定的数量,将会把队列中最老的线程静默丢弃,把新的放进来
4. CallerRunsPolicy: 实际线程数量大于维护队列中设定的数量,多出来的线程由调用线程(主线程)处理
推荐使用ThreadPoolTaskExecutor创建线程池
@Configuration
public class ThreadPoolConfig {
@Bean(name = "testThreadPool")
public ThreadPoolTaskExecutor createPool(){
ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();
//线程池所使用的缓冲队列
poolTaskExecutor.setQueueCapacity(60);
//线程池维护线程的最少数量
poolTaskExecutor.setCorePoolSize(3);
//线程池维护线程的最大数量
poolTaskExecutor.setMaxPoolSize(5);
//线程前缀名称
poolTaskExecutor.setThreadNamePrefix("testThreadPool");
/**
* 总共有四种拒绝策略,实际线程数量超过线程池设定的数量,将会启用拒绝策略
* 1. AbortPolicy(默认拒绝策略): 实际线程数量大于维护队列中设定的数量,将会触发拒绝任务的处理程序,它将抛出RejectedExecutionException
* 2. DiscardPolicy: 实际线程数量大于维护队列中设定的数量,将会被静默丢弃
* 3. DiscardOldestPolicy: 实际线程数量大于维护队列中设定的数量,将会把队列中最老的线程静默丢弃,把新的放进来
* 4. CallerRunsPolicy: 实际线程数量大于维护队列中设定的数量,多出来的线程由调用线程(主线程)处理
*/
poolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//默认是60s,线程池中启用的线程,空闲时间超过这个时间就会被销毁
poolTaskExecutor.setKeepAliveSeconds(60);
poolTaskExecutor.initialize();
return poolTaskExecutor;
}
}
CallerRunsPolicy这个拒绝策略不好理解,测试用例如下(说白了就是:所有线程都会被执行,从干不过来了,主帮忙干)
public static void main(String[] args) {
ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();
poolTaskExecutor.setQueueCapacity(5);
poolTaskExecutor.setCorePoolSize(3);
poolTaskExecutor.setMaxPoolSize(5);
poolTaskExecutor.setThreadNamePrefix("callerRunsPolicyTest");
poolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
poolTaskExecutor.setKeepAliveSeconds(60);
poolTaskExecutor.initialize();
long start = System.currentTimeMillis();
for (int i = 0; i < 20; i++) {
poolTaskExecutor.submit(() -> {
try {
System.out.println(Thread.currentThread().getName() + ":执行任务");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
long end = System.currentTimeMillis();
System.out.println("主线程完成任务,耗时:" + (end - start)/1000 + "秒,主线程名为:" + Thread.currentThread().getName());
}
输出结果:
callerRunsPolicyTest2:执行任务
callerRunsPolicyTest3:执行任务
callerRunsPolicyTest1:执行任务
callerRunsPolicyTest4:执行任务
main:执行任务
callerRunsPolicyTest5:执行任务
main:执行任务
callerRunsPolicyTest1:执行任务
callerRunsPolicyTest5:执行任务
callerRunsPolicyTest2:执行任务
callerRunsPolicyTest3:执行任务
callerRunsPolicyTest4:执行任务
callerRunsPolicyTest4:执行任务
callerRunsPolicyTest5:执行任务
callerRunsPolicyTest3:执行任务
callerRunsPolicyTest2:执行任务
主线程完成任务,耗时:2秒,主线程名为:main
callerRunsPolicyTest1:执行任务
callerRunsPolicyTest2:执行任务
callerRunsPolicyTest3:执行任务
callerRunsPolicyTest1:执行任务