SpringBoot

Spring Boot @Async 使用线程池

2019-03-27  本文已影响0人  CallMe兵哥

前提条件

使用异步线程池的前提是大家已经知道如何构建一个可以异步调用的Web工程,如果还有不明白的请移步https://www.jianshu.com/p/7482721e3ac8

在前一章节的基础下,做如下修改:

  1. 新建一个线程配置类:ThreadPoolTaskConfig
    要点:
    1)增加@Configuration注解,确定是配置类。
    2)增加@EnableAsync,把异步服务开启转移到线程配置类。
@Configuration
@EnableAsync
public class ThreadPoolTaskConfig {

    private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() *2;
    private static final int MAX_POOL_SIZE = CORE_POOL_SIZE *4 <256 ? 256 : CORE_POOL_SIZE * 4;
    private static final int KEEP_ALIVE_TIME = 10; //允许线程空闲时间(单位为秒)
    private static final int QUEUE_CAPACITY = 200; // 缓冲队列数
    private static final int AWAIT_TERMINATION = 60;//线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁
    private static final Boolean WAIT_FOR_TASKS_TO_COMPLETE_ON_SHUTDOWN = true;//用来设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean
    private static final String THREAD_NAME_PREFIX = "PiceaAsync-Service-"; // 线程池名前缀

    /**
     * <p>"@Bean("piceaTaskExecutor"),Bean后面的()内容可以省略
     * 如果省略则使用方法名<p>
     * @author jiangbing.yang
     * @date   2019/3/27 11:07
     * @params
     * @return
     * @throws
     */

    @Bean("piceaTaskExecutor")
    public ThreadPoolTaskExecutor piceaTaskExecutor () {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(CORE_POOL_SIZE);
        taskExecutor.setMaxPoolSize(MAX_POOL_SIZE);
        taskExecutor.setKeepAliveSeconds(KEEP_ALIVE_TIME);
        taskExecutor.setQueueCapacity(QUEUE_CAPACITY);
        taskExecutor.setThreadNamePrefix(THREAD_NAME_PREFIX);
        taskExecutor.setWaitForTasksToCompleteOnShutdown(WAIT_FOR_TASKS_TO_COMPLETE_ON_SHUTDOWN);
        taskExecutor.setAwaitTerminationSeconds(AWAIT_TERMINATION);
        // 线程池对拒绝任务的处理策略
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化
        taskExecutor.initialize();
        return taskExecutor;
    }
}
  1. 在控制类中增加输出线程名称
@RestController
public class PiceaContoller {

    @Autowired
    private PiceaService piceaService;

    @RequestMapping("/asyncTask")
    public void asyncTask() throws Exception {
        System.out.println("在控制层调用的线程名:"+ Thread.currentThread().getName());
        piceaService.asyncTask();
    }

    @RequestMapping("/asyncTaskFuture")
    public String asyncTaskFuture() throws Exception {
        System.out.println("在控制层调用的线程名:"+ Thread.currentThread().getName());
        String ret = null;
        //异步先执行任务1
        Future<String> future = piceaService.asyncTaskFuture();
        //异步执行任务2
        Future<String> future2 = piceaService.asyncTaskFuture2();
        String ret1 = null;
        String ret2 = null;
        //获取任务1执行结果
        while (true) {
            if (future.isDone()){
                ret1 = future.get();
                break;
            }
        }
        //获取任务2执行结果
        while (true) {
            if (future2.isDone()) {
                ret2 = future2.get();
                break;
            }
        }
        //任务1结果+任务2结果
        ret = ret1 + "+" + ret2;
        //最终返回任何合集
        return  ret;
    }
}
  1. 删除启动类的@EnableAsync注解
@SpringBootApplication
public class SpringBootAsync2Application {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootAsync2Application.class, args);
    }

}
  1. 测试结果
    以下结果,可以明显看出在控制层的线程名称和服务层的线程名称不一样。


    Spring-boot-asyncFuture-ThreadPool.png

打雷下雨,回家收衣服啦。

其它注意

本文SpringBoot版本为2.1.3
本文章样例:
工程名:spring-boot-async-2
GitHub:https://github.com/zzyjb/SpringBootLearning

  1. Web工程Async异步请移步
    https://www.jianshu.com/p/7482721e3ac8
  2. 自定义线程池-本章
    https://www.jianshu.com/p/dabd65f617bb
  3. 异步异常处理请移步
    https://www.jianshu.com/p/11c78717799b
上一篇下一篇

猜你喜欢

热点阅读