@EnableAsync与@Async
在使用多线程的时候,往往需要创建Thread类,或者实现Runnable接口,如果要使用到线程池,我们还需要来创建Executors,在使用spring中,已经给我们做了很好的支持。只要要@EnableAsync就可以使用多线程。使用@Async就可以定义一个线程任务。通过spring给我们提供的ThreadPoolTaskExecutor就可以使用线程池。
1. @EnableAsync开始对异步任务的支持
@Configuration
@EnableAsync
public class ThreadPoolTaskConfig {
private static final int corePoolSize = 10; // 核心线程数(默认线程数)
private static final int maxPoolSize = 100; // 最大线程数
private static final int keepAliveTime = 10; // 允许线程空闲时间(单位:默认为秒)
private static final int queueCapacity = 200; // 缓冲队列数
private static final String threadNamePrefix = "Async-Service-"; // 线程池名前缀
@Bean("taskExecutor") // bean的名称,默认为首字母小写的方法名
public ThreadPoolTaskExecutor getAsyncExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveTime);
executor.setThreadNamePrefix(threadNamePrefix);
// 线程池对拒绝任务的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 初始化
executor.initialize();
return executor;
}
}
2. @Async(“线程池名称”)注解来声明一个或多个异步任务
(1)加在类上,表示这个类的所有方法都是异步的。
(2)加在方法上,表示该方法是异步的。
@Async("taskExecutor")
public void test(testParam param) {
方法内容
}
3.@Async调用中的事务处理机制
在@Async标注的方法,同时也适用了@Transactional进行了标注;在其调用数据库操作之时,将无法产生事务管理的控制,原因就在于其是基于异步处理的操作。
那该如何给这些操作添加事务管理呢?可以将需要事务管理操作的方法放置到异步方法内部,在内部被调用的方法上添加@Transactional.
(1)使用了@Async/@Transactional来标注,但是无法产生事务控 制的目的。
(2)使用了@Async来标注,B中调用了C、D,C/D分别使用 @Transactional做了标注,则可实现事务控制的目的。
4.@Async失效
(1)异步方法使用static修饰
(2)异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类
(3)异步方法不能与异步方法在同一个类中
(4)类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
(5)如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解
(6)在Async 方法上标注@Transactional是没用的。 在Async 方法调用的方法上标注@Transactional 有效。
(7)调用被@Async标记的方法的调用者不能和被调用的方法在同一类中不然不会起作用!!!!!!!
(8)使用@Async时要求是不能有返回值的不然会报错的 因为异步要求是不关心结果的