环境:springboot2.3.9.RELEASE
如果上下文中没有Executor Bean,Spring Boot会自动配置ThreadPoolTaskExecutor,使其具有可自动关联到异步任务执行(@EnableSync)
系统默认配置
public static final String APPLICATION_TASK_EXECUTOR_BEAN_NAME = "applicationTaskExecutor";
@Bean
@ConditionalOnMissingBean
public TaskExecutorBuilder taskExecutorBuilder(TaskExecutionProperties properties,
ObjectProvider<TaskExecutorCustomizer> taskExecutorCustomizers,
ObjectProvider<TaskDecorator> taskDecorator) {
TaskExecutionProperties.Pool pool = properties.getPool();
TaskExecutorBuilder builder = new TaskExecutorBuilder();
builder = builder.queueCapacity(pool.getQueueCapacity());
builder = builder.corePoolSize(pool.getCoreSize());
builder = builder.maxPoolSize(pool.getMaxSize());
builder = builder.allowCoreThreadTimeOut(pool.isAllowCoreThreadTimeout());
builder = builder.keepAlive(pool.getKeepAlive());
Shutdown shutdown = properties.getShutdown();
builder = builder.awaitTermination(shutdown.isAwaitTermination());
builder = builder.awaitTerminationPeriod(shutdown.getAwaitTerminationPeriod());
builder = builder.threadNamePrefix(properties.getThreadNamePrefix());
builder = builder.customizers(taskExecutorCustomizers.orderedStream()::iterator);
builder = builder.taskDecorator(taskDecorator.getIfUnique());
return builder;
}
@Lazy
@Bean(name = { APPLICATION_TASK_EXECUTOR_BEAN_NAME,AsyncAnnotationBeanPostProcessor.DEFAULT_TASK_EXECUTOR_BEAN_NAME })
@ConditionalOnMissingBean(Executor.class)
public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
return builder.build();
}
@ConditionalOnMissingBean当前环境中没有Bean是配置该Bean。
可以通过如下属性进行线程池相关参数的配置。
自定义ThreadPoolTaskExecutor
@Bean
public ThreadPoolTaskExecutor customThreadPoolExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor() ;
executor.setCorePoolSize(10) ;
executor.setMaxPoolSize(10) ;
executor.setKeepAliveSeconds(60) ;
executor.setThreadGroupName("Orders-Group") ;
executor.setThreadNamePrefix("order-async-") ;
return executor ;
}
测试是否生效
启动类添加开启异步任务注解
@SpringBootApplication
@EnableAsync
public class SpringBootComprehensiveApplication
@Async
@GetMapping("/task")
public Object task() {
System.out.println(Thread.currentThread().getName()) ;
return "success" ;
}
输出了我们配置的线程信息。
自定义Executor Bean
当系统中存在Executor Bean时,系统会使用SimpleAsyncTaskExecutor线程池
@Bean
public Executor asyncExecutor() {
ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(),new ThreadFactory() {
ThreadGroup group = new ThreadGroup("Orders-JUC-Group") ;
private final AtomicInteger threadNumber = new AtomicInteger(1);
String threadPrefix = "order-juc-async-";
@Override
public Thread newThread(Runnable r) {
return new Thread(group, r, threadPrefix + threadNumber.getAndIncrement()) ;
}
}) ;
return executor ;
}
测试:
注意系统默认的异步任务线程池
@Lazy
@Bean(name = { APPLICATION_TASK_EXECUTOR_BEAN_NAME,AsyncAnnotationBeanPostProcessor.DEFAULT_TASK_EXECUTOR_BEAN_NAME })
@ConditionalOnMissingBean(Executor.class)
public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {
return builder.build();
}
@ConditionalOnMissingBean(Executor.class)注意这里,只有当前没有Executor Bean的时候才会创建ThreadPoolTaskExecutor线程池。所以这时候applicationTaskExecutor Bean也不会生效了。系统中配置的ThreadPoolExecutor Bean并不会应用到异步任务的执行。
注意:现在bean name 是 asyncExecutor,把其改为taskExecutor。再运行
自定义线程池ThreadPoolExecutor生效了。查看源码
AsyncAnnotationBeanPostProcessor
@Nullable
private Supplier<Executor> executor;
/**
* Set the {@link Executor} to use when invoking methods asynchronously.
* <p>If not specified, default executor resolution will apply: searching for a
* unique {@link TaskExecutor} bean in the context, or for an {@link Executor}
* bean named "taskExecutor" otherwise. If neither of the two is resolvable,
* a local default executor will be created within the interceptor.
* @see AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory)
* @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
*/
public void setExecutor(Executor executor) {
this.executor = SingletonSupplier.of(executor);
}
注释大意是:在上下文中搜索TaskExecutor Bean,如果没有再找名为taskExecutor 的Bean。
自定义AsyncConfigurer实现线程池
通过自定义AsyncConfigurer类可以使用JUC中的ThreadPoolExecutor线程池。
@Component
public class CustomAsyncConfigurer implements AsyncConfigurer {
private static Logger logger = LoggerFactory.getLogger(CustomAsyncConfigurer.class) ;
@Override
public Executor getAsyncExecutor() {
ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(),new ThreadFactory() {
ThreadGroup group = new ThreadGroup("Orders-JUC-Group") ;
private final AtomicInteger threadNumber = new AtomicInteger(1);
String threadPrefix = "order-juc-async-";
@Override
public Thread newThread(Runnable r) {
return new Thread(group, r, threadPrefix + threadNumber.getAndIncrement()) ;
}
}) ;
return executor ;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncUncaughtExceptionHandler() {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
logger.error("method: {}, params: {}, ex: {}", method.getName(), Arrays.toString(params), ex) ;
}
};
}
}
这里查看源码就明白了。
进入父类:
AbstractAsyncConfiguration.java
自动装配AsyncConfigurer。
测试:
自定义的ThreadPoolExecutor已生效。
完毕!!!
给个关注+转发呗谢谢
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/80030.html