概述
当一个方法标注@Async注解时,该方法的调用将异步发生;这意味着调用者将在调用后立即返回,方法的实际执行将发生在提交给Spring TaskExecutor的任务中。
示例
示例1
使用@EnableAsync注解启用异步机制
@EnableAsync @Configuration public class AsyncConfig { }
@Service public class AsyncJob { @Async public void asyncMethodWithVoidReturnType() { System.out.println("Execute method asynchronously: start." + Thread.currentThread().getName()); try { Thread.sleep(10 * 1000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Execute method asynchronously: end." + Thread.currentThread().getName()); } }
@RestController @RequestMapping("/home") public class HomeController { @Autowired private AsyncJob asyncJob; @GetMapping("/user-info") public String queryUserName() { asyncJob.asyncMethodWithVoidReturnType(); return "test - user"; } }
运行结果
Postman
日志
从上述日志中线程的名称可以知道,本示例中异步执行方法所用的线程池为Spring boot默认配置的线程池(TaskExecutionAutoConfiguration)
示例2
自定义线程池
@Configuration public class ThreadPoolConfig { @Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor poolExecutor = new ThreadPoolTaskExecutor(); // 核心线程数 poolExecutor.setCorePoolSize(1); // 最大线程数 poolExecutor.setMaxPoolSize(3); // 队列大小 poolExecutor.setQueueCapacity(5); // 线程最大空闲时间 poolExecutor.setKeepAliveSeconds(60); // 拒绝策略 poolExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); // 线程名称前缀 poolExecutor.setThreadNamePrefix("sendMessage-"); return poolExecutor; } }
@Service public class AsyncJob { @Async("taskExecutor") public void asyncMethodWithVoidReturnType() { System.out.println("Execute method asynchronously: start." + Thread.currentThread().getName()); try { Thread.sleep(10 * 1000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Execute method asynchronously: end." + Thread.currentThread().getName()); } }
public class AsyncJobTest extends BaseTest { @Autowired private AsyncJob asyncJob; @Test void check_async() { System.out.println("check_async. " + Thread.currentThread().getName()); asyncJob.asyncMethodWithVoidReturnType(); try { Thread.sleep(30 * 1000L); } catch (InterruptedException e) { e.printStackTrace(); } } }
运行结果
特别说明
如果项目中配置了多个线程池,在@Async注解中必须指明具体的线程池,否则会有如下类似报错
(1)多个线程池,且其中某个线程池的名称为taskExecutor
本质原因:ThreadPoolTaskScheduler、ThreadPoolTaskExecutor都是org.springframework.core.task.TaskExecutor的子类
(2)多个线程池,且任何线程池的名称均不为taskExecutor
此时将使用默认构建的线程池(即SimpleAsyncTaskExecutor的实例)异步执行方法
具体细节见下一章
揭秘 - 线程池
(1)通过@Async注解指定线程池的秘密
(2)使用Spring boot默认线程池(即:taskExecutor) 或者 SimpleAsyncTaskExecutor 的秘密
Future
如果@Async方法需要返回运行结果,可声明方法返回值为Future类型:
A、可以声明为常规的Java .util.concurrent. future类型
B、可以声明为Spring的org.springframework.util.concurrent.ListenableFuture类型
C、从Spring 4.2开始也可以声明为Java中的CompletableFuture
@Service public class AsyncJob { @Async public CompletableFuture<Integer> getEmployeeCount() { int count = 0; // ... return CompletableFuture.completedFuture(count); } }
扩展阅读
How To Do @Async in Spring | Baeldung
标签:异步,Thread,poolExecutor,Spring,线程,Async,public From: https://www.cnblogs.com/studyLog-share/p/14988363.html