@Async 异步注解使用
使用版本SpringBoot-2.7.18
使用@EnableAsync开启异步注解
java
@EnableAsync
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
在需要的方法上加上@Async
java
@Service
public class TestServiceImpl implements TestService {
@Override
@Async
public LocalDateTime async() {
return LocalDateTime.now();
}
}
Spring Boot使用的异步任务执行器
默认情况异步任务执行器使用ThreadPoolTaskExecutor
在 org.springframework.aop.interceptor.AsyncExecutionInterceptor.invoke() 方法中打断点可以看到使用的是哪个线程池
java
@Override
@Nullable
public Object invoke(final MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
//1、这里打个断点可以看到使用的是哪个线程池
AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
if (executor == null) {
throw new IllegalStateException(
"No executor specified and no default executor set on AsyncExecutionInterceptor either");
}
Callable<Object> task = () -> {
try {
Object result = invocation.proceed();
if (result instanceof Future) {
return ((Future<?>) result).get();
}
}
catch (ExecutionException ex) {
handleError(ex.getCause(), userDeclaredMethod, invocation.getArguments());
}
catch (Throwable ex) {
handleError(ex, userDeclaredMethod, invocation.getArguments());
}
return null;
};
return doSubmit(task, executor, invocation.getMethod().getReturnType());
}
直接配置一个异步任务执行器,使用@Async注解,异步任务执行器会更改成 myTaskExecutorA
java
@Configuration
public class BeanConfigure {
@Bean
TaskExecutor myTaskExecutorA() {
return new MyTaskExecutorA();
}
public static class MyTaskExecutorA implements TaskExecutor {
@Override
public void execute(Runnable task) {
System.err.println("==========》" + task.getClass());
}
}
}
恰巧我们配置了两个异步任务执行器,会切换使用 org.springframework.core.task.SimpleAsyncTaskExecutor
java
@Configuration
public class BeanConfigure {
@Bean
TaskExecutor myTaskExecutorA() {
return new MyTaskExecutorA();
}
@Bean
TaskExecutor myTaskExecutorB() {
return new MyTaskExecutorB();
}
public static class MyTaskExecutorA implements TaskExecutor {
@Override
public void execute(Runnable task) {
System.err.println("==========》" + task.getClass());
}
}
public static class MyTaskExecutorB implements TaskExecutor {
@Override
public void execute(Runnable task) {
System.err.println("==========》" + task.getClass());
}
}
}
首先, org.springframework.core.task.SimpleAsyncTaskExecutor执行效果不是很好;其次,项目中的其他业务可能会配置使用多于两个的TaskExecutor,所以使用@Async的最佳实践是为其明确指定异步任务执行器:@Async("myTaskExecutorA")
java
@Service
public class TestServiceImpl implements TestService {
@Override
@Async("myTaskExecutorA")//明确指定需要使用的异步执行器
public LocalDateTime async() {
return LocalDateTime.now();
}
}