国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring定時任務@scheduled多線程的使用(@Async注解)

klivitamJ / 2268人閱讀

摘要:下面我們稍稍改下代碼來證實一下這次我讓任務執行的時間等于,大于條線程總間隔時間來耗盡線程池中的線程。

1.開篇

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

2.使用@Async

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

@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的執行時間內,下一個任務并沒有等待上一個任務結束,而是在任務開始時間直接開啟了一條新的線程進行執行。
仔細觀察結果我們還可以發現,每條結果都是一條新的線程,直到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");
    }

這次我讓任務執行的時間等于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條線程也開始執行任務后,沒有新的線程再被創建,而是等待有線程執行完后,再開始執行本次任務。

3.配置線程池大小

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

    
    
    

測試代碼:

@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條線程使用完畢以后就會等待之前的線程釋放啦,同時也可以看到線程池名是我們設置的線程池。

如有錯誤,歡迎留言指正,謝謝大家!

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69750.html

相關文章

  • Spring定時任務高級使用

    摘要:定時任務高級使用篇前面一篇博文之定時任務基本使用篇介紹了環境下,定時任務的簡單使用姿勢,也留了一些問題,這一篇則希望能針對這些問題給個答案定時任務進階篇問題小結前面一篇博文,拋出了下面的幾個問題,接下來則圍繞問題進行分析一個項目中有多個定時 showImg(https://segmentfault.com/img/remote/1460000015880327); Spring定時任務...

    dcr309duan 評論0 收藏0
  • Spring 定時任務

    摘要:在定時器接口的方法中我們可以發現一個方法接受接口,而也是一個接口,抽象了觸發任務執行的觸發器。更常用的一個觸發器是,它使用表達式指定何時執行任務。配置定時任務首先看看配置。配置提供了命名空間,讓配置定時任務非常簡單。 本文參考自Spring官方文檔 34. Task Execution and Scheduling。 在程序中常常有定時任務的需求,例如每隔一周生成一次報表、每個月月末清...

    justCoding 評論0 收藏0
  • SpringBoot中并發定時任務實現、動態定時任務實現(看這一篇就夠了)

    摘要:也是自帶的一個基于線程池設計的定時任務類。其每個調度任務都會分配到線程池中的一個線程執行,所以其任務是并發執行的,互不影響。 原創不易,如需轉載,請注明出處https://www.cnblogs.com/baixianlong/p/10659045.html,否則將追究法律責任!!! 一、在JAVA開發領域,目前可以通過以下幾種方式進行定時任務 1、單機部署模式 Timer:jdk中...

    BWrong 評論0 收藏0
  • Spring線程池和定時任務功能

    摘要:同時使用框架自己定義的抽象接口來屏蔽掉底層版本間以及中的線程池和定時任務處理的差異。配置文件如下所示完成配置后即可使用此線程池。 1.功能介紹 Spring框架提供了線程池和定時任務執行的抽象接口:TaskExecutor和TaskScheduler來支持異步執行任務和定時執行任務功能。同時使用框架自己定義的抽象接口來屏蔽掉底層JDK版本間以及Java EE中的線程池和定時任務處理的差...

    xeblog 評論0 收藏0
  • Spring Boot(四)Spring Boot 中定時任務

    摘要:對于定時任務類如果不定義線程池,控制臺輸出如下,可以看到不同的定時任務是同一個線程在執行在配置類或者啟動類中增加定時任務的線程池控制臺輸出本節示例代碼已上傳到 一.SpringBoot中開啟定時任務 在spirngboot中使用定時任務非常簡單,只需要在啟動類上增加一個@EnableScheduling注解即可。 @SpringBootApplication @EnableSchedu...

    firim 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<