5、Async

Spring封装了一个异步方法的实现,使得方法可以在单独的线程中异步执行,提高系统的并发能力和响应性能。

相关注解

注解 说明
@Async 将方法标记为异步执行的方法,在方法上添加@Async注解后,方法的调用将会在一个单独的线程中异步执行。
@EnableAsync 在Spring配置类上使用该注解来启用异步处理功能

注意事项

注意:如果报错Null return value from advice does not match primitive return type for,需要将异步方法的返回值改为包装类,因为框架内部做了AOP处理,不管是cglib代理还是jdk代理,你的返回值都必须是包装类。

代码示例

1、在启动类添加注解@EnableAsync用于异步执行注解,并且使用spring默认线程池;也可以使用配置类开启,并且自定义线程池

@Configuration
@EnableAsync
public class AsyncThreadPoolConfig {

    /**
     *  默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,
     *  当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;
     *  当队列满了,就继续创建线程,当线程数量大于等于maxPoolSize后,开始使用拒绝策略拒绝
     */

    /** 核心线程数(默认线程数) */
    private static final int corePoolSize = 20;
    /** 最大线程数 */
    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") // 默认Spring会找这个名字的线程池
    public ThreadPoolTaskExecutor taskExecutor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAliveTime);
        executor.setThreadNamePrefix(threadNamePrefix);

        // 线程池对拒绝任务的处理策略
        // CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化
        executor.initialize();
        return executor;
    }
}

2、在需要异步执行的方法上添加注解@Async(),value为使用的线程池,不写则为默认线程池byName = taskExcutor

@Service  
public class TranTest2Service {  
    Logger log = LoggerFactory.getLogger(TranTest2Service.class);  
  
    // 使用自定义线程池
    @Async("taskExecutor")  
    public void sendMessage1() throws InterruptedException {  
        // business
    }  
  
    @Async("taskExecutor")  
    public void sendMessage2() throws InterruptedException {  
        // business  
    }  
}