spring boot中的异步执行(@EnableAsync,@Async)

来源:互联网 发布:urlencoder js 解码 编辑:程序博客网 时间:2024/06/12 22:50

过去使用spring3.x,很可能这样写一段代码执行一个异步的任务:

    @Autowired    ThreadPoolTaskExecutor executor;    public void dosomething() {        executor.execute(new Runnable() {            @Override            public void run() {            }        });    }

现在看看spring boot中是如何处理的:
1. 首先通过@EnableAsync开启异步执行的功能,这可以放在springboot主类上,或者放在我们的配置类上。
2. 配置自定义的线程池(如果不自定义的话,springboot会提供默认的)。
我这边是把@EnableAsync放在了自定义线程池的配置上。

@Configuration@EnableAsyncpublic class ExecutorConfig {    @Bean    public Executor firstExecutor() {        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();        executor.setCorePoolSize(10);        executor.setMaxPoolSize(20);        executor.setQueueCapacity(10);        executor.setThreadNamePrefix("firstExecutor-");        executor.initialize();        return executor;    }    @Bean    public Executor secondExecutor() {        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();        executor.setCorePoolSize(20);        executor.setMaxPoolSize(100);        executor.setQueueCapacity(20);        executor.setThreadNamePrefix("secondExecutor-");        executor.initialize();        return executor;    }}

这边配置了两个线程池,后面会知道如何指定使用的线程池。
注:一般生产中线程池参数往往会从配置文件中获取,获取方式可以看这篇文章:
spring boot 通过@Value,@ConfigurationProperties获取配置
3. 配置执行类

@Componentpublic class Task {    @Async("firstExecutor")    public Future<String> exec1() throws InterruptedException {        System.out.println(Thread.currentThread().getName() + " exec1 开始:" + new Date());        Thread.sleep(2000L);        System.out.println(Thread.currentThread().getName() + " exec1 结束:" + new Date());        return new AsyncResult<>("exec1");    }    @Async("secondExecutor")    public Future<String> exec2() throws InterruptedException {        System.out.println(Thread.currentThread().getName() + " exec2 开始:" + new Date());        Thread.sleep(4000L);        System.out.println(Thread.currentThread().getName() + " exec2 结束:" + new Date());        return new AsyncResult<>("exec2");    }    @Async("secondExecutor")    public Future<String> exec3() throws InterruptedException {        System.out.println(Thread.currentThread().getName() + " exec3 开始:" + new Date());        Thread.sleep(4000L);        System.out.println(Thread.currentThread().getName() + " exec3 结束:" + new Date());        return new AsyncResult<>("exec3");    }}

@Async: 注解的方法表示为异步执行的方法,值为指定的线程池,当只有一个自定义的线程池或使用默认线程池时,值可以省略。
4. 测试类

@RunWith(SpringRunner.class)@SpringBootTestpublic class ExecutorMynotesApplicationTests {    @Autowired    private Task task;    @Test    public void contextLoads() throws InterruptedException, ExecutionException {        Future<String> future1 = task.exec1();        Future<String> future2 = task.exec2();        Future<String> future3 = task.exec3();        future1.get();        future2.get();        future3.get();    }}

执行结果:

secondExecutor-1 exec2 开始:Fri Sep 01 10:02:37 CST 2017firstExecutor-1 exec1 开始:Fri Sep 01 10:02:37 CST 2017secondExecutor-2 exec3 开始:Fri Sep 01 10:02:37 CST 2017firstExecutor-1 exec1 结束:Fri Sep 01 10:02:39 CST 2017secondExecutor-2 exec3 结束:Fri Sep 01 10:02:41 CST 2017secondExecutor-1 exec2 结束:Fri Sep 01 10:02:41 CST 2017

代码