Spingboot项目中异步任务线程池配置方式

导读:本篇文章讲解 Spingboot项目中异步任务线程池配置方式,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

环境: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。

可以通过如下属性进行线程池相关参数的配置。

Spingboot项目中异步任务线程池配置方式

 

自定义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" ;
}

Spingboot项目中异步任务线程池配置方式

 

输出了我们配置的线程信息。

自定义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 ;
}

测试:

Spingboot项目中异步任务线程池配置方式

 

注意系统默认的异步任务线程池

@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。再运行

Spingboot项目中异步任务线程池配置方式

 

自定义线程池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) ;
      }
    };
  }
}

这里查看源码就明白了。

Spingboot项目中异步任务线程池配置方式

 

进入父类:
AbstractAsyncConfiguration.java

Spingboot项目中异步任务线程池配置方式

 

自动装配AsyncConfigurer。

测试:

Spingboot项目中异步任务线程池配置方式

 

自定义的ThreadPoolExecutor已生效。

完毕!!!

给个关注+转发呗谢谢

Spingboot项目中异步任务线程池配置方式

 

Spingboot项目中异步任务线程池配置方式

 

Spingboot项目中异步任务线程池配置方式

 

Spingboot项目中异步任务线程池配置方式

Spingboot项目中异步任务线程池配置方式

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/80030.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!