@Async 异步注解使用

@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();
	}
}
相关推荐
爱读源码的大都督20 分钟前
为什么有了HTTP,还需要gPRC?
java·后端·架构
码事漫谈21 分钟前
致软件新手的第一个项目指南:阶段、文档与破局之道
后端
间彧21 分钟前
Spring Boot条件注解详解与项目实战
后端
im_AMBER38 分钟前
Web 开发 27
前端·javascript·笔记·后端·学习·web
Lucky_Turtle39 分钟前
【Java Xml】Apache Commons Digester3解析
xml·java·apache
间彧39 分钟前
ApplicationRunner与CommandLineRunner详解与应用实战
后端
聪明的笨猪猪1 小时前
Java Redis “缓存设计”面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
FIavor.1 小时前
我发送给Apifox是http://localhost:9002/goods/getByUserName?name=张三 为什么会是500哪里错了?
java·服务器·网络协议·http
ID_180079054731 小时前
京东获取整站实时商品详情数据|商品标题|数据分析提取教程
java·开发语言
微露清风2 小时前
系统性学习C++-第五讲-内存管理
java·c++·学习