WHAT
@Async由Spring定义,在方法上添加此注解,方法的执行将会是异步的(在另一个线程中执行),调用者不需要等待方法执行完成
1 2 3 4 5 6 7
| @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Async { // 用于指定异步执行的线程池名称 String value() default ""; }
|
WHY
被@Async标记的方法都可以异步执行,注解的方式非常灵活,异步的线程资源可以集中管理
异步执行 BEFORE
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public void sayWorld() { new Thread(() -> { try { TimeUnit.SECONDS.sleep(30); System.out.println("world"); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); }
public void sayHello() { sayWorld(); System.out.println("hello"); }
|
异步执行 AFTER
1 2 3 4 5 6 7 8 9 10 11
| @Async public void sayWorld() throws InterruptedException { TimeUnit.SECONDS.sleep(30); System.out.println("world"); }
public void sayHello() { sayWorld(); System.out.println("hello"); }
|
HOW
@Async如何使用?又是怎么运作的?
事例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| @Configuration @EnableAsync public class AsyncConfigDemo implements AsyncConfigurer { // 优先级低,相对于 @Async指定异步线程池
@Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor(); threadPoolTaskExecutor.setCorePoolSize(10); threadPoolTaskExecutor.setThreadNamePrefix("async-"); threadPoolTaskExecutor.initialize(); return threadPoolTaskExecutor; }
@Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return new SimpleAsyncUncaughtExceptionHandler(); } }
@Service public class AsyncDemo { @Async(value = "taskScheduler") // 优先级高 public void sayWorld() throws InterruptedException { TimeUnit.SECONDS.sleep(3); System.out.println("world"); } }
// 使用
@Resource private AsyncDemo asyncDemo;
@Test public void testSync() throws IOException { try { asyncDemo.sayWorld(); System.out.println("hello"); System.in.read(); } catch (InterruptedException e) { e.printStackTrace(); } }
|
原理
AsyncConfigDemo由ConfigurationClassParser进行解析,包括注解@EnableAsync上的AsyncConfigurationSelector类
AsyncConfigurationSelector根据@EnableAsync mode()选择代理方式实现,默认为ProxyAsyncConfiguration
Configuration类ProxyAsyncConfiguration被创建并注入AsyncConfigurer扩展的executor、exceptionHandler,创建AsyncAnnotationBeanPostProcessor并通过setBeanFactory方法创建AsyncAnnotationAdvisor
AsyncAnnotationAdvisor设置advice(AnnotationAsyncExecutionInterceptor,设置缺省获取线程池方法getDefaultExecutor,当未扩展AsyncConfigurer的实现则在执行异步的时候getDefaultExecutor会从Spring的上下文中查找TaskExecutor的实现类实例)。设置pointcut(@Async的注解类或方法或是自定义的异步注解)
AnnotationAsyncExecutionInterceptor通过determineAsyncExecutor方法确认执行的Executor。getExecutorQualifier方法查找名为@Async指定的value值的Executor,若找到则执行,若无法确认Executor则调用getDefaultExecutor方法查询类型为TaskExecutor的类,若有多个实现则会查找名字为”taskExecutor”的实现Bean,最终都没有找到则创建SimpleAsyncTaskExecutor(每一个异步的方法任务都会创建一个新的线程)
All you got in life is people. That’s all there is. - Tony
Green Book