天天看點

Spring Boot配置線程池與異步注解@Async的使用

一、@Async注解簡介

Spring為任務排程與異步方法執行提供了注解支援。通過在方法上設定@Async注解,可使得方法被異步調用。也就是說調用者會在調用時立即傳回,而被調用方法的實際執行是交給Spring的TaskExecutor來完成。

二、配置與使用

我們可以使用springBoot預設的線程池,不過一般我們會自定義線程池(因為比較靈活)

@Configuration
@EnableAsync
public class TaskExecutorConfig {

    /**
     * 建立異步調用的線程池
     * @return
     */
    @Bean("taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(200);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("taskExecutor-");
        // 用來設定線程池關閉的時候等待所有任務都完成再繼續銷毀其他的Bean,這樣這些異步任務的銷毀就會先于Redis線程池的銷毀
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 設定線程池中任務的等待時間,如果超過這個時候還沒有銷毀就強制銷毀,以確定應用最後能夠被關閉,而不是阻塞住
        executor.setAwaitTerminationSeconds(60);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
}
           

編寫異步方法

@Service
public class AsyncTaskService {

    @Async("taskExecutor")
    public void doTask(){
        try {
            Thread.sleep(5 * 1000);
            System.out.println("睡眠完成");
        } catch (Exception e){
            System.out.println(e.getMessage());
        }
    }
}
           

進行測試

/**
     * 修改使用者
     *
     * @return 結果
     */
    @GetMapping("/task")
    @ResponseBody
    public Map<String, Object> task() {
        System.out.println("---- 執行前 -------");
        asyncTaskService.doTask();
        System.out.println("---- 執行後 -------");

        Map<String, Object> resultMap = new HashMap<>(16);
        resultMap.put("code", 200);
        resultMap.put("msg", "執行成功");
        return resultMap;
    }
           

通路 http://localhost:8765/task

Spring Boot配置線程池與異步注解@Async的使用

異步調用成功

三、注意事項

如下方式會使@Async失效

  • 異步方法使用static修飾
  • 異步類沒有使用@Component注解(或其他注解)導緻spring無法掃描到異步類
  • 異步方法不能與被調用的異步方法在同一個類中
  • 類中需要使用@Autowired或@Resource等注解自動注入,不能自己手動new對象
  • 如果使用SpringBoot架構必須在啟動類中增加@EnableAsync注解

繼續閱讀