SpringBoot中使用@EnableAsync
和@Async
注解来实现异步任务功能,具体有如下三种方式,可自定义的程度依次递增。
方式一
Application
启动类上加上@EnableAsync
注解
package com.example.demo_asynctask;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@EnableAsync
@SpringBootApplication
public class DemoAsynctaskApplication {
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(DemoAsynctaskApplication.class, args);
}
}
异步方法上加上@Async
注解(注意异步方法的调用方不可以和异步方法在同一个类中)
package com.example.demo_asynctask;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class AsyncTask {
@Async
public void task1() throws InterruptedException {
Long beginTime = System.currentTimeMillis();
Thread.sleep(1000L);
Long endTime = System.currentTimeMillis();
System.out.println("异步任务一,耗时:" + (endTime - beginTime) + "ms.");
}
}
调用方示例
package com.example.demo_asynctask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@Autowired
AsyncTask asyncTask;
@GetMapping("/test")
public void test() throws InterruptedException {
Long beginTime = System.currentTimeMillis();
asyncTask.task1();
Long endTime = System.currentTimeMillis();
System.out.println("调用函数,执行耗时:" + (endTime - beginTime) + "ms.");
}
}
访问http://localhost:8080/test
,控制台输出如下,证明调用方执行完毕时,异步任务仍在执行。
方式二
直接在Application
启动类上加@EnableAsync
注解不优雅,并且我们可能想自定义线程池的一些属性,因此去掉启动类上的注解,添加如下配置类
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.initialize();
return executor;
}
}
异步任务类和调用类保持原样,即
@Component
public class AsyncTask {
@Async
public void task1() throws InterruptedException {
Long beginTime = System.currentTimeMillis();
Thread.sleep(1000L);
Long endTime = System.currentTimeMillis();
System.out.println("异步任务一,耗时:" + (endTime - beginTime) + "ms.");
}
}
@RestController
public class TestController {
@Autowired
AsyncTask asyncTask;
@GetMapping("/test")
public void test() throws InterruptedException {
Long beginTime = System.currentTimeMillis();
asyncTask.task1();
Long endTime = System.currentTimeMillis();
System.out.println("调用函数,执行耗时:" + (endTime - beginTime) + "ms.");
}
}
继续访问http://localhost:8080/test
,控制台输出如下,
方式三
有时候我们想在不同的场景中使用不同的线程池来执行异步任务,有些需要更多的核心线程,有些需要更多的队列容量,为此需要创建多个配置类,例如
@Configuration
@EnableAsync
public class AsyncCustomConfig {
@Bean("myAsyncExecutor")
public Executor myAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(3);
executor.setMaxPoolSize(5);
executor.initialize();
return executor;
}
}
然后再异步任务的@Aync
上指定线程池,即
@Component
public class AsyncTask {
@Async("myAsyncExecutor")
public void task1() throws InterruptedException {
Long beginTime = System.currentTimeMillis();
Thread.sleep(1000L);
Long endTime = System.currentTimeMillis();
System.out.println("异步任务一,耗时:" + (endTime - beginTime) + "ms.");
}
}
调用类保持不变
@RestController
public class TestController {
@Autowired
AsyncTask asyncTask;
@GetMapping("/test")
public void test() throws InterruptedException {
Long beginTime = System.currentTimeMillis();
asyncTask.task1();
Long endTime = System.currentTimeMillis();
System.out.println("调用函数,执行耗时:" + (endTime - beginTime) + "ms.");
}
}
继续访问http://localhost:8080/test
,控制台输出如下,
网友评论