最近项目中用到了该注解,对其查找线程池的顺序比较困惑,查阅资料简单整理在此。
注意的点
* 必须用在public方法上
* 在某异步方法的同一个类的其他方法调用此异步方法无效
Spring的异步配置
要激活Spring的异步行为,可以为配置类添加@EnableAsync注解。
@EnableAsync @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }
@EnableAsync 检测@Async注解。
基本用法
该注解用到需要用其他线程处理任务的方法上。
不带任何返回值的用法
@Override @Async public void createUserWithDefaultExecutor(){ //SimpleAsyncTaskExecutor System.out.println("Currently Executing thread name - " + Thread.currentThread().getName()); System.out.println("User created with default executor"); }
默认Spring会搜索容器中唯一的TaskExecutor类型的Bean,或名为taskExecutor的Executor类型的bean。
如果两者都找不到,一个SimpleAsyncTaskExecutor任务执行器将被用来处理该注解的任务。
带返回值的用法
@Override @Async public Future createAndReturnUser() { System.out.println("Currently Executing thread name - " + Thread.currentThread().getName()); try { User user = new User(); user.setFirstName("John"); user.setLastName("Doe"); user.setGender("Male"); Thread.sleep(5000); return new AsyncResult(user); } catch (InterruptedException e) { System.out.println(e.getMessage()); } return null; }
下面是测试方法:
@Test public void createAndReturnUserTest() throws ExecutionException, InterruptedException { System.out.println("Current Thread in test class " + Thread.currentThread().getName()); long startTime = System.currentTimeMillis(); Future futureUser = userService.createAndReturnUser(); futureUser.get(); assertTrue((System.currentTimeMillis() - startTime) >= 5000); }
定义范例
Spring默认用SimpleAsyncTaskExecutor来处理@Async注解的任务。
我们还可以利用参考下面的示例来自定义方法级别的处理器。
@Bean(name = "threadPoolExecutor") public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(7); executor.setMaxPoolSize(42); executor.setQueueCapacity(11); executor.setThreadNamePrefix("threadPoolExecutor-"); executor.initialize(); return executor; }