Spring Boot 自定义异步线程池的两种方式

Mr. Zheng
2019-11-06 / 0 评论 / 3,007 阅读 / 正在检测收录...
温馨提示:
本文最后更新于2021年06月23日,已超过38天没有更新,若内容或图片失效,请留言反馈。

kq95f4hi.png

第一种

  1. 创建自定义线程池配置类,AsyncTaskExecutePool
@EnableAsync
@Configuration
public class AsyncTaskExecutePool {

    //核心线程池大小
    private final int corePoolSize = 10;
    //最大线程数
    private final int maxPoolSize = 15;
    //队列容量
    private final int queueCapacity = 50;
    //活跃时间/秒
    private final int keepAliveSeconds = 60;

    @Bean
    public Executor myAsyncTaskPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程池大小
        executor.setCorePoolSize(corePoolSize);
        //最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //队列容量
        executor.setQueueCapacity(queueCapacity);
        //活跃时间
        executor.setKeepAliveSeconds(keepAliveSeconds);
        //设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //线程名字前缀
        executor.setThreadNamePrefix("my-async1--");
        // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
        // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}
  1. 创建任务处理类AsyncTask
@Component
@Slf4j
public class AsyncTask {

    /**
     * myAsyncTaskPool 线程池的方法名,此处如果不写,会使用Spring默认的线程池
     * @param i
     */
    @Async("myAsyncTaskPool")
    public void run(int i){
       log.info("我是:" + i);
    }
}
  1. 测试线程池AppTests
@SpringBootTest
class AppTests {

    @Autowired
    private AsyncTask asyncTask;

    @Test
    void test(){
        for (int i = 0; i < 100; i++) {
            asyncTask.run(i);
        }
    }
}

运行查看效果

第二种

第二种方式是重写 spring 默认线程池,使用这种方式的好处是可以直接使用 @Async 注解

  1. 创建配置类AsyncTaskExecutePool1 并且实现AsyncConfigurer
@Slf4j
@EnableAsync
@Configuration
public class AsyncTaskExecutePool1 implements AsyncConfigurer {

    //核心线程池大小
    private final int corePoolSize = 10;
    //最大线程数
    private final int maxPoolSize = 15;
    //队列容量
    private final int queueCapacity = 50;
    //活跃时间/秒
    private final int keepAliveSeconds = 60;

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程池大小
        executor.setCorePoolSize(corePoolSize);
        //最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //队列容量
        executor.setQueueCapacity(queueCapacity);
        //活跃时间
        executor.setKeepAliveSeconds(keepAliveSeconds);
        //设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //线程名字前缀
        executor.setThreadNamePrefix("my-async-");
        // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
        // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

     /**
     * 异步任务异常处理
     * @return
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (throwable, method, objects) -> {
            log.error("===="+throwable.getMessage()+"====", throwable);
            log.error("exception method:"+method.getName());
        };
    }
}
  1. 修改AsyncTask 类,在类中加入方法run1
@Async
public void run1(int i){
    log.info("我是:" + i);
}
  1. 测试,在AppTests 中加入方法test1
@Test
void test1(){
    for (int i = 0; i < 100; i++) {
        asyncTask.run1(i);
    }
}

运行查看效果

注意

  1. 同类中调用带有@Async 的方法是不生效的
  2. 例子中的参数根据具体的需求修改

源码

本文源码:https://github.com/elunez/spring-boot-learn

1

评论 (0)

取消