欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring定時任務@scheduled多線程使用@Async注解示例

 更新時間:2023年11月24日 10:58:00   作者:怕翻船的忒修斯  
這篇文章主要為大家介紹了Spring定時任務@scheduled多線程使用@Async注解示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

1.開篇

Spring定時任務@Scheduled注解使用方式淺窺這篇文章里面提及過,spring的定時任務默認是單線程的,他在某些場景下會造成堵塞,那么如果我們想讓每一個任務都起一條線程去執(zhí)行呢?

2.使用@Async

我們可以使用Spring的@Async注解十分容易的實現多線程的任務執(zhí)行。
測試代碼:

@Scheduled(cron = "0/2 * * * * ?")
    @Async
    public void doTask() throws InterruptedException {
        logger.info(Thread.currentThread().getName()+"===task run");
        Thread.sleep(6*1_000);
        logger.info(Thread.currentThread().getName()+"===task end");
    }

結果日志

2018-06-12 16:02:42.005 [taskExecutor-97] INFO  service.task.testTask -taskExecutor-97===task run
2018-06-12 16:02:42.007 [taskExecutor-94] INFO  service.task.testTask -taskExecutor-94===task end
2018-06-12 16:02:44.004 [taskExecutor-98] INFO  service.task.testTask -taskExecutor-98===task run
2018-06-12 16:02:44.015 [taskExecutor-95] INFO  service.task.testTask -taskExecutor-95===task end
2018-06-12 16:02:46.004 [taskExecutor-99] INFO  service.task.testTask -taskExecutor-99===task run
2018-06-12 16:02:46.014 [taskExecutor-96] INFO  service.task.testTask -taskExecutor-96===task end
2018-06-12 16:02:48.004 [taskExecutor-100] INFO  service.task.testTask -taskExecutor-100===task run
2018-06-12 16:02:48.010 [taskExecutor-97] INFO  service.task.testTask -taskExecutor-97===task end
2018-06-12 16:02:50.005 [taskExecutor-1] INFO  service.task.testTask -taskExecutor-1===task run
2018-06-12 16:02:50.008 [taskExecutor-98] INFO  service.task.testTask -taskExecutor-98===task end
2018-06-12 16:02:52.006 [taskExecutor-2] INFO  service.task.testTask -taskExecutor-2===task run

截取部分結果日志我們可以看到,在上一個任務6s的執(zhí)行時間內,下一個任務并沒有等待上一個任務結束,而是在任務開始時間直接開啟了一條新的線程進行執(zhí)行。
仔細觀察結果我們還可以發(fā)現,每條結果都是一條新的線程,直到100時,才又從第一條線程開始。這是因為在默認不做配置的情況下,@Async所使用的線程池容量為100,每次需要的時候都會從中拿出一條,直到用完,才會等待之前的線程釋放,不會再自己擴容。
下面我們稍稍改下代碼來證實一下:

@Scheduled(cron = "0/2 * * * * ?")
    @Async
    public void doTask() throws InterruptedException {
        logger.info(Thread.currentThread().getName()+"===task run");
        Thread.sleep(300*1_000);
        logger.info(Thread.currentThread().getName()+"===task end");
    }

這次我讓任務執(zhí)行的時間等于300s,大于100條線程總間隔時間來耗盡線程池中的線程。

結果日志

2018-06-12 16:26:44.411 [taskExecutor-93] INFO  service.task.testTask -taskExecutor-93===task run
2018-06-12 16:26:46.853 [taskExecutor-94] INFO  service.task.testTask -taskExecutor-94===task run
2018-06-12 16:26:48.008 [taskExecutor-95] INFO  service.task.testTask -taskExecutor-95===task run
2018-06-12 16:26:50.008 [taskExecutor-96] INFO  service.task.testTask -taskExecutor-96===task run
2018-06-12 16:26:52.006 [taskExecutor-97] INFO  service.task.testTask -taskExecutor-97===task run
2018-06-12 16:26:54.008 [taskExecutor-98] INFO  service.task.testTask -taskExecutor-98===task run
2018-06-12 16:26:56.006 [taskExecutor-99] INFO  service.task.testTask -taskExecutor-99===task run
2018-06-12 16:26:58.005 [taskExecutor-100] INFO  service.task.testTask -taskExecutor-100===task run

2018-06-12 16:28:40.142 [taskExecutor-1] INFO  service.task.testTask -taskExecutor-1===task end
2018-06-12 16:28:40.149 [taskExecutor-1] INFO  service.task.testTask -taskExecutor-1===task run
2018-06-12 16:28:42.117 [taskExecutor-2] INFO  service.task.testTask -taskExecutor-2===task end
2018-06-12 16:28:42.121 [taskExecutor-2] INFO  service.task.testTask -taskExecutor-2===task run
2018-06-12 16:28:44.253 [taskExecutor-3] INFO  service.task.testTask -taskExecutor-3===task end
2018-06-12 16:28:44.257 [taskExecutor-3] INFO  service.task.testTask -taskExecutor-3===task run
2018-06-12 16:28:46.027 [taskExecutor-4] INFO  service.task.testTask -taskExecutor-4===task end
2018-06-12 16:28:46.031 [taskExecutor-4] INFO  service.task.testTask -taskExecutor-4===task run

通過日志我們可以看到,再第100條線程也開始執(zhí)行任務后,沒有新的線程再被創(chuàng)建,而是等待有線程執(zhí)行完后,再開始執(zhí)行本次任務。

3.配置線程池大小

雖然上面的方式已經解決了我們的問題,但是總覺得不太好,有時候我們需要異步執(zhí)行任務,但是又不需要這么多的線程的時候,我們可以使用下面的配置來設置線程池的大小
配置文件:

<task:annotation-driven scheduler="testScheduler" />
    <!-- 配置任務線程池和線程池大小 -->
    <task:scheduler id="testScheduler" pool-size="6" />

測試代碼:

@Scheduled(cron = "0/2 * * * * ?")
    @Async
    public void doTask() throws InterruptedException {
        logger.info(Thread.currentThread().getName()+"===task run");
        Thread.sleep(6*1_000);
        logger.info(Thread.currentThread().getName()+"===task end");
    }

結果日志:

2018-06-12 18:32:56.032 [taskExecutor-1] INFO  service.task.testTask -taskExecutor-1===task run
2018-06-12 18:32:58.007 [taskExecutor-2] INFO  service.task.testTask -taskExecutor-2===task run
2018-06-12 18:33:00.005 [taskExecutor-3] INFO  service.task.testTask -taskExecutor-3===task run
2018-06-12 18:33:02.008 [taskExecutor-4] INFO  service.task.testTask -taskExecutor-4===task run
2018-06-12 18:33:02.036 [taskExecutor-1] INFO  service.task.testTask -taskExecutor-1===task end
2018-06-12 18:33:04.327 [taskExecutor-2] INFO  service.task.testTask -taskExecutor-2===task end
2018-06-12 18:33:04.328 [taskExecutor-5] INFO  service.task.testTask -taskExecutor-5===task run
2018-06-12 18:33:06.007 [taskExecutor-6] INFO  service.task.testTask -taskExecutor-6===task run
2018-06-12 18:33:06.010 [taskExecutor-3] INFO  service.task.testTask -taskExecutor-3===task end
2018-06-12 18:33:08.459 [taskExecutor-4] INFO  service.task.testTask -taskExecutor-4===task end
2018-06-12 18:33:08.460 [taskExecutor-7] INFO  service.task.testTask -taskExecutor-7===task run
2018-06-12 18:33:10.011 [taskExecutor-8] INFO  service.task.testTask -taskExecutor-8===task run
2018-06-12 18:33:10.332 [taskExecutor-5] INFO  service.task.testTask -taskExecutor-5===task end
2018-06-12 18:33:12.005 [taskExecutor-9] INFO  service.task.testTask -taskExecutor-9===task run
2018-06-12 18:33:12.012 [taskExecutor-6] INFO  service.task.testTask -taskExecutor-6===task end
2018-06-12 18:33:14.904 [taskExecutor-10] INFO  service.task.testTask -taskExecutor-10===task run
2018-06-12 18:33:14.904 [taskExecutor-7] INFO  service.task.testTask -taskExecutor-7===task end

結果和我們預料的并不一樣啊,線程數超過了6,這是什么原因呢?

其實如果我們在使用@Async時想使用配置好的線程池,需要為@Async注解添加value屬性來制定所用的線程池。
修改后的代碼

@Scheduled(cron = "0/2 * * * * ?")
    @Async("testScheduler")
    public void doTask() throws InterruptedException {
        logger.info(Thread.currentThread().getName()+"===task run");
        Thread.sleep(30*1_000);
        logger.info(Thread.currentThread().getName()+"===task end");
    }

結果日志:

2018-06-12 18:54:42.035 [testScheduler-3] INFO  service.task.testTask -testScheduler-3===task run
2018-06-12 18:54:44.010 [testScheduler-2] INFO  service.task.testTask -testScheduler-2===task run
2018-06-12 18:54:46.007 [testScheduler-1] INFO  service.task.testTask -testScheduler-1===task run
2018-06-12 18:54:48.007 [testScheduler-5] INFO  service.task.testTask -testScheduler-5===task run
2018-06-12 18:54:50.005 [testScheduler-4] INFO  service.task.testTask -testScheduler-4===task run
2018-06-12 18:54:52.021 [testScheduler-6] INFO  service.task.testTask -testScheduler-6===task run

2018-06-12 18:55:12.039 [testScheduler-3] INFO  service.task.testTask -testScheduler-3===task end
2018-06-12 18:55:12.044 [testScheduler-3] INFO  service.task.testTask -testScheduler-3===task run
2018-06-12 18:55:14.016 [testScheduler-2] INFO  service.task.testTask -testScheduler-2===task end
2018-06-12 18:55:14.022 [testScheduler-2] INFO  service.task.testTask -testScheduler-2===task run
2018-06-12 18:55:16.289 [testScheduler-1] INFO  service.task.testTask -testScheduler-1===task end
2018-06-12 18:55:16.297 [testScheduler-1] INFO  service.task.testTask -testScheduler-1===task run
2018-06-12 18:55:18.289 [testScheduler-5] INFO  service.task.testTask -testScheduler-5===task end
2018-06-12 18:55:18.293 [testScheduler-5] INFO  service.task.testTask -testScheduler-5===task run
2018-06-12 18:55:20.009 [testScheduler-4] INFO  service.task.testTask -testScheduler-4===task end
2018-06-12 18:55:20.014 [testScheduler-4] INFO  service.task.testTask -testScheduler-4===task run
2018-06-12 18:55:22.165 [testScheduler-6] INFO  service.task.testTask -testScheduler-6===task end
2018-06-12 18:55:22.172 [testScheduler-6] INFO  service.task.testTask -testScheduler-6===task run

這次結果和我們的預計是一樣的了,在初始的6條線程使用完畢以后就會等待之前的線程釋放啦,同時也可以看到線程池名是我們設置的線程池。

以上就是Spring定時任務@scheduled多線程使用@Async注解示例的詳細內容,更多關于Spring @scheduled使用@Async的資料請關注腳本之家其它相關文章!

相關文章

  • JavaI/O深入學習之輸入和輸出

    JavaI/O深入學習之輸入和輸出

    這篇文章主要介紹了JavaI/O深入學習之輸入和輸出,Java類庫中的I/O類分成輸入和輸出兩部分,可以在JDK文檔里的類層次結構中查看到。,需要的朋友可以參考下
    2019-06-06
  • 玩轉SpringBoot2快速整合攔截器的方法

    玩轉SpringBoot2快速整合攔截器的方法

    這篇文章主要介紹了玩轉SpringBoot2快速整合攔截器的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • Java線程中的關鍵字和方法示例詳解

    Java線程中的關鍵字和方法示例詳解

    這篇文章主要介紹了Java有關線程中的關鍵字和方法,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • Intellij Idea修改代碼方法參數自動提示快捷鍵的操作

    Intellij Idea修改代碼方法參數自動提示快捷鍵的操作

    這篇文章主要介紹了Intellij Idea修改代碼方法參數自動提示快捷鍵的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • springboot獲取真實ip地址的方法實例

    springboot獲取真實ip地址的方法實例

    在使用springboot時,需要獲取訪問客戶端的IP地址,所以下面這篇文章主要給大家介紹了關于springboot獲取真實ip地址的相關資料,需要的朋友可以參考下
    2022-06-06
  • Java多線程編程之使用Exchanger數據交換實例

    Java多線程編程之使用Exchanger數據交換實例

    這篇文章主要介紹了Java多線程編程之使用Exchanger數據交換實例,本文直接給出實例代碼,需要的朋友可以參考下
    2015-05-05
  • Java數據結構之紅黑樹的實現方法和原理詳解

    Java數據結構之紅黑樹的實現方法和原理詳解

    這篇文章主要介紹了Java數據結構之紅黑樹的實現方法和原理,紅黑樹是一種特殊的二叉查找樹,每個結點都要儲存位表示結點的顏色,或紅或黑,本文將通過示例為大家詳細講講紅黑樹的原理及實現,感興趣的朋友可以了解一下
    2024-02-02
  • Spring?Boot的幾種統(tǒng)一處理方式梳理小結

    Spring?Boot的幾種統(tǒng)一處理方式梳理小結

    這篇文章主要為大家介紹了Spring?Boot的幾種統(tǒng)一處理方式梳理小結,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • Java代理模式的示例詳解

    Java代理模式的示例詳解

    代理模式(Proxy?Parttern)為一個對象提供一個替身,來控制這個對象的訪問,即通過代理對象來訪問目標對象。本文將通過示例詳細講解一下這個模式,需要的可以參考一下
    2022-08-08
  • SpringBoot 中使用JSP的方法示例

    SpringBoot 中使用JSP的方法示例

    本篇文章主要介紹了SpringBoot 中使用JSP的方法示例,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06

最新評論