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

过去使用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
@EnableAsync
public 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. 配置执行类

@Component
public 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)
@SpringBootTest
public class ExecutorMynotesApplicationTests {

    @Autowired
    private Task task;

    @Test
    public void contextLoads() throws InterruptedException, ExecutionException {
        Future future1 = task.exec1();
        Future future2 = task.exec2();
        Future future3 = task.exec3();
        future1.get();
        future2.get();
        future3.get();
    }

}

执行结果:

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

代码

你可能感兴趣的:(spring-boot,spring-boot,异步,线程池,Async)