springboot 內建異步線程池
目的:通過實作AsyncConfigurer自定義線程池,包含異常處理。 實作AsyncConfigurer接口對異常線程池更加細粒度的控制
/**
* @Description: 線程池配置
* @Author: mingtian
* @CreateDate: 2020/11/12 15:57
* @Version: 1.0
*/
@Configuration
@EnableAsync
public class ThreadPoolConfig implements AsyncConfigurer {
/**
* 列印日志
*/
private Logger logger = LoggerFactory.getLogger(getClass());
/**
* cpu 核心數量
*/
public static final int cpuNum = Runtime.getRuntime().availableProcessors();
/**
* 線程池配置
*
* @return
*/
@Bean("taskExecutor")
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
// 配置核心線程池數量
taskExecutor.setCorePoolSize(cpuNum);
// 配置最大線程池數量
taskExecutor.setMaxPoolSize(cpuNum * 2);
/// 線程池所使用的緩沖隊列
taskExecutor.setQueueCapacity(2);
// 等待時間 (預設為0,此時立即停止),并沒等待xx秒後強制停止
taskExecutor.setAwaitTerminationSeconds(60);
// 空閑線程存活時間
taskExecutor.setKeepAliveSeconds(60);
// 等待任務在關機時完成--表明等待所有線程執行完
taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
// 線程池名稱字首
taskExecutor.setThreadNamePrefix("thread-pool-");
// 線程池拒絕政策
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
// 線程池初始化
taskExecutor.initialize();
logger.info("線程池初始化......");
return taskExecutor;
}
/**
* 重寫捕獲異常類
*
* @return
*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new MyAsyncExceptionHandler();
}
/**
* 自定義異常處理類
*/
class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
//手動處理捕獲的異常
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
logger.error("ExceptionMessage:{}", throwable.getMessage());
logger.error("MethodName:{}", method.getName());
for (Object param : obj) {
logger.error("Parameter:{}", param);
}
}
}
}
模拟發送消息業務層
1 /**
2 * @Description: 模拟異步發送消息方法
3 * @Author: mingtian
4 * @CreateDate: 2020/11/12 16:29
5 * @Version: 1.0
6 */
7 @Component
8 public class SendMessageService {
9 /**
10 * 列印日志
11 */
12 private Logger logger = LoggerFactory.getLogger(getClass());
13
14 @Async
15 public void sendMessage() {
16 logger.info("發送消息");
17 System.out.println("子線程名稱:" + Thread.currentThread().getName());
18 }
19 }
測試類
1 /**
2 * @Description: 測試類
3 * @Author: mingtian
4 * @CreateDate: 2020/11/12 16:30
5 * @Version: 1.0
6 */
7 @RunWith(SpringRunner.class)
8 @SpringBootTest
9 public class Test {
10 @Autowired
11 private SendMessageService messageService;
12
13 @org.junit.Test
14 public void testAsync() {
15 System.out.println("主線程名稱:" + Thread.currentThread().getName());
16 for (int i = 0; i < 100; i++) {
17 messageService.sendMessage();
18 }
19
20 }
21 }
控制台列印結果:
主線程名稱:main
2020-11-12 16:47:48.985 INFO 16728 --- [ thread-pool-6] c.example.threadpool.SendMessageService : 異步發送發送消息
2020-11-12 16:47:48.985 INFO 16728 --- [ thread-pool-5] c.example.threadpool.SendMessageService : 異步發送發送消息
2020-11-12 16:47:48.985 INFO 16728 --- [ thread-pool-6] c.example.threadpool.SendMessageService : 異步發送發送消息
2020-11-12 16:47:48.985 INFO 16728 --- [ thread-pool-7] c.example.threadpool.SendMessageService : 異步發送發送消息
2020-11-12 16:47:48.985 INFO 16728 --- [ thread-pool-5] c.example.threadpool.SendMessageService : 異步發送發送消息
2020-11-12 16:47:48.985 INFO 16728 --- [ thread-pool-8] c.example.threadpool.SendMessageService : 異步發送發送消息
2020-11-12 16:47:48.985 INFO 16728 --- [ thread-pool-4] c.example.threadpool.SendMessageService : 異步發送發送消息
2020-11-12 16:47:48.985 INFO 16728 --- [ thread-pool-1] c.example.threadpool.SendMessageService : 異步發送發送消息
2020-11-12 16:47:48.985 INFO 16728 --- [ thread-pool-3] c.example.threadpool.SendMessageService : 異步發送發送消息
2020-11-12 16:47:48.985 INFO 16728 --- [ thread-pool-2] c.example.threadpool.SendMessageService : 異步發送發送消息
由以上的結果得出配置的線程池是有效的。