多線程注解@Async的使用


多線程注解@Async的使用

1.在啟動類Application中添加注解@EnableAsync

2.啟動類需要實現AsyncConfigurer

3.配置線程池

    //配置線程池
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        /** 核心線程數(默認線程數) */
        taskExecutor.setCorePoolSize(25);
         /** 最大線程數 */
        taskExecutor.setMaxPoolSize(50);
         /** 緩沖隊列大小 */
        taskExecutor.setQueueCapacity(25);
         /** 允許線程空閑時間(單位:默認為秒) */
        taskExecutor.setKeepAliveSeconds(300);
         // 線程池對拒絕任務的處理策略
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
        taskExecutor.initialize();
        return taskExecutor;
    }
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }

實際項目中最大允許的線程數為75個,核心+隊列+max(50-核心)

4.在需要異步的方法中加入@Async,此時需要考慮線程同步問題,可使用CountDownLatch

//對每個數據源開啟一個線程
long start = System.currentTimeMillis();
CountDownLatch countDownLatch = new CountDownLatch(map.size());
for (Integer dbids : map.keySet()) {
    List<Integer> integerList = map.get(dbids);
    //異步處理
    mentService.dealData(countDownLatch, integerList, list);
}
countDownLatch.await();
long end = System.currentTimeMillis();
System.out.println("查詢信息花費:" + (end - start));
@Async
public void dealData(CountDownLatch countDownLatch, List<Integer> integerList,List<Map<String, Object>> list) {
    logger.info("當前線程名字" + Thread.currentThread().getName());
    try {
       
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        countDownLatch.countDown();
    }

}

CountDownLatch的用法:

CountDownLatch是一個同步工具類,用來協調多個線程之間的同步,構造CountDownLatch的時候需要傳入一個整數n,在這個整數“倒數”到0之前,主線程需要等待在門口,而這個“倒數”過程則是由各個執行線程驅動的,每個線程執行完一個任務“倒數”一次。總結來說,CountDownLatch的作用就是等待其他的線程都執行完任務,必要時可以對各個任務的執行結果進行匯總,然后主線程才繼續往下執行。

@Async注解的注意事項:

1.@SpringBootApplication啟動類當中沒有添加@EnableAsync注解。

2.方法是公有的

3.異步代碼,需要放在外部單獨的類中,不能在同一個類中調用同一個方法,否則會是同步處理

( 據說這是一個“常識”,外部方法才會被Spring攔截器攔截到額),沒有走Spring的代理類。因為@Transactional和@Async注解的實現都是基於Spring的AOP,而AOP的實現是基於動態代理模式實現的。那么注解失效的原因就很明顯了,有可能因為調用方法的是對象本身而不是代理對象,因為沒有經過Spring容器管理。也可以通過自己注入自己的方式)

4.異步方法使用注解@Async的返回值只能為void或者Future

5.debug斷點調試情況下是看不出效果的,可通過在調用后打印時間在異步方法中打印時間的方式查看,如果要debug程序代碼,可以把注解注釋掉

線程的運行說明:

execute(Runable)方法執行過程

如果此時線程池中的數量小於corePoolSize,即使線程池中的線程都處於空閑狀態,也要創建新的線程來處理被添加的任務。

如果此時線程池中的數量等於 corePoolSize,但是緩沖隊列 workQueue未滿,那么任務被放入緩沖隊列。

如果此時線程池中的數量大於corePoolSize,緩沖隊列workQueue滿,並且線程池中的數量小於maxPoolSize,建新的線程來處理被添加的任務。

如果此時線程池中的數量大於corePoolSize,緩沖隊列workQueue滿,並且線程池中的數量等於maxPoolSize,那么通過handler所指定的策略來處理此任務。也就是:處理任務的優先級為:核心線程corePoolSize、任務隊列workQueue、最大線程 maximumPoolSize,如果三者都滿了,使用handler處理被拒絕的任務。

當線程池中的線程數量大於corePoolSize時,如果某線程空閑時間超過keepAliveTime,線程將被終止。這樣,線程池可以動態的調整池中的線程數

具體信息參照https://www.cnblogs.com/redcool/p/6426173.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM