org.springframework.scheduling.annotation.Async
如果使用时没有明确指定线程池,会发生什么?
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
org.springframework.boot.task.TaskExecutorBuilder
前文已经交代过所有异步任务放在一起不合适,而且第一种和第三种的默认实现还有更加严重的问题。
# PART.01
ThreadPoolTaskExecutor
先来看 ThreadPoolTaskExecutor。
SpringBoot 默认使用 TaskExecutionProperties 类来配置构建 ThreadPoolTaskExecutor线程池。
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
org.springframework.boot.autoconfigure.task.TaskExecutionProperties
我们可以看到 队列容量 和 最大线程数 都是 Integer.MAX_VALUE,这非常可怕。
spring.task.execution.pool.core-size: 核心线程数
spring.task.execution.pool.max-size: 最大线程数
spring.task.execution.pool.queue-capacity: 队列容量
spring.task.execution.pool.keep-alive: 线程终止前允许保持的空闲时间
spring.task.execution.pool.allow-core-thread-timeout: 是否允许核心线程超时
spring.task.execution.thread-name-prefix: 线程名称前缀
# PART.02
SimpleAsyncTaskExecutor
SimpleAsyncTaskExecutor 默认每次执行异步任务的时候都会创建一个新的线程,问题同样严重。
# PART.03
创建自己的线程池
@Bean
public Executor asyncExecutorService() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(8);
executor.setMaxPoolSize(16);
executor.setQueueCapacity(1000);
executor.setKeepAliveSeconds(300);
executor.setThreadNamePrefix("My-Executor-");
// 执行装饰器
executor.setTaskDecorator((runnable) -> {
// 获取上级线程中的一些信息,一般存放在ThreadLocal中。
long tid = Thread.currentThread().getId();
return () -> {
try {
if (Thread.currentThread().getId() != tid) {
// 将上级线程中获取的信息存到子线程中
}
runnable.run();
} finally {
if (Thread.currentThread().getId() != tid) {
// 清空子线程ThreadLocal
}
}
};
});
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
点个
原文始发于微信公众号(i余数):为什么建议 “在使用SpringBoot的@Async注解时一定要指定线程池?”
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/194112.html