Spring中的@Async | 8lovelife's life
0%

Spring中的@Async

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();
}
}

原理

  1. AsyncConfigDemo由ConfigurationClassParser进行解析,包括注解@EnableAsync上的AsyncConfigurationSelector

  2. AsyncConfigurationSelector根据@EnableAsync mode()选择代理方式实现,默认为ProxyAsyncConfiguration

  3. Configuration类ProxyAsyncConfiguration被创建并注入AsyncConfigurer扩展的executor、exceptionHandler,创建AsyncAnnotationBeanPostProcessor并通过setBeanFactory方法创建AsyncAnnotationAdvisor

  4. AsyncAnnotationAdvisor设置advice(AnnotationAsyncExecutionInterceptor,设置缺省获取线程池方法getDefaultExecutor,当未扩展AsyncConfigurer的实现则在执行异步的时候getDefaultExecutor会从Spring的上下文中查找TaskExecutor的实现类实例)。设置pointcut(@Async的注解类或方法或是自定义的异步注解)

  5. 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