Spring Boot异步任务:@Async

it2024-07-25  37

介绍

异步是相对于同步而言的,同步是指程序按预定顺序执行,每一步必须等到上一步完成后再执行,异步则无需等待上一步程序执行完即可执行。通常使用多线程来实现。

使用说明

1、引用依赖

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 工具类,简化常用代码:get,set,toString等 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <optional>true</optional> </dependency>

2、线程池配置

application.properties

#***** thread ***** #线程池中线程的最少数量 thread.pool.corePoolSize=8 #线程池中线程的最大数量 thread.pool.maxPoolSize=16 #所允许的空闲时间 thread.pool.keepAliveSeconds=300 #等待队列的大小 thread.pool.queueCapacity=32 /** * 线程池配置 * @author yanyuan */ @Data @ConfigurationProperties(prefix = "thread.pool") public class ThreadPoolConfig { private int corePoolSize; private int maxPoolSize; private int keepAliveSeconds; private int queueCapacity; } ```java /** * 创建线程池 * EnableAsync 开启异步的支持 * @Author yanyuan * */ @Configuration @EnableAsync @EnableConfigurationProperties(ThreadPoolConfig.class) public class TaskExecutePool { @Autowired private ThreadPoolConfig config; @Bean("taskAsyncPool") public Executor taskAsyncPool() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //核心线程池大小 executor.setCorePoolSize(config.getCorePoolSize()); //最大线程数 executor.setMaxPoolSize(config.getMaxPoolSize()); //队列容量 executor.setQueueCapacity(config.getQueueCapacity()); //活跃时间 executor.setKeepAliveSeconds(config.getKeepAliveSeconds()); //线程名字前缀 executor.setThreadNamePrefix("executor-"); // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务 // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } }

3、异步任务方法

/** * @author: yanyuan * @Date: 2020/11/11 18:49 * @Description: 异步任务 */ @Component @Slf4j public class AsyncTask { public String doTask() throws InterruptedException { log.info("thread name = {}, message = {}", Thread.currentThread().getName(), "task start"); //等待3秒 TimeUnit.SECONDS.sleep(3); log.info("thread name = {}, message = {}", Thread.currentThread().getName(), "task end"); return "task complete"; } /** * Async 对某个方法进行异步执行 * @return * @throws InterruptedException */ @Async("taskAsyncPool") public Future<String> doAsyncTask() throws InterruptedException { log.info("thread name = {}, message = {}", Thread.currentThread().getName(), "async start"); //等待3秒 TimeUnit.SECONDS.sleep(3); log.info("thread name = {}, message = {}", Thread.currentThread().getName(), "async end"); return new AsyncResult<>("async execute complete"); } }

4、Controller测试

/** * @author: yanyuan * @Date: 2020/11/11 19:24 * @Description: */ @RestController @Slf4j public class TaskController { @Autowired AsyncTask asyncTask; @GetMapping("task") public String task() throws InterruptedException, ExecutionException { long times = System.currentTimeMillis(); asyncTask.doTask(); return "任务执行耗时:"+ (System.currentTimeMillis() - times) + "ms"; } /** * 异步任务 * @return * @throws InterruptedException * @throws ExecutionException */ @GetMapping("async-task") public String asyncTask() throws InterruptedException, ExecutionException { long times = System.currentTimeMillis(); asyncTask.doAsyncTask(); return "任务执行耗时:"+ (System.currentTimeMillis() - times) + "ms"; } /** * 异步任务-获取执行结果 * @return * @throws InterruptedException * @throws ExecutionException */ @GetMapping("async-wait-result") public String asyncWaitResult() throws InterruptedException, ExecutionException { Future<String> future = asyncTask.doAsyncTask(); while (true) { if(future.isDone()){ log.info("async task complete, result = {}", future.get()); return "异步执行结果:" + future.get(); } } } }

启动项目:

访问同步任务:http://localhost:8080/task 接口返回结果:任务执行耗时:3008ms 控制台日志: 2020-11-12 09:27:53.511 INFO 314716 — [nio-8080-exec-1] com.yanyuan.first.task.AsyncTask : thread name = http-nio-8080-exec-1, message = task start 2020-11-12 09:27:56.513 INFO 314716 — [nio-8080-exec-1] com.yanyuan.first.task.AsyncTask : thread name = http-nio-8080-exec-1, message = task end

访问异步任务:http://localhost:8080/async-task 接口返回结果:任务执行耗时:5ms 控制台日志: 2020-11-12 09:30:34.278 INFO 314716 — [ executor-1] com.yanyuan.first.task.AsyncTask : thread name = executor-1, message = async start 2020-11-12 09:30:37.294 INFO 314716 — [ executor-1] com.yanyuan.first.task.AsyncTask : thread name = executor-1, message = async end

访问异步任务并等待异步结果:http://localhost:8080/async-wait-result 接口返回结果:异步执行结果:async execute complete 控制台日志: 2020-11-12 09:32:28.546 INFO 314716 — [ executor-2] com.yanyuan.first.task.AsyncTask : thread name = executor-2, message = async start 2020-11-12 09:32:31.547 INFO 314716 — [ executor-2] com.yanyuan.first.task.AsyncTask : thread name = executor-2, message = async end 2020-11-12 09:32:31.547 INFO 314716 — [nio-8080-exec-9] c.y.first.controller.TaskController : async task complete, result = async execute complete

参考资料

项目地址 分支:async-task

最新回复(0)