最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中定時任務的全方位場景實現(xiàn)思路分析

 更新時間:2023年12月22日 08:14:08   作者:沒感情的程序員  
在開發(fā)過程中,根據(jù)需求和業(yè)務的不同經(jīng)常會有很多場景需要用到不同特性的定時任務,本文將針對這些場景,提供不同的一個實現(xiàn)思路,感興趣的小伙伴快跟隨小編一起學習一下吧

定時任務場景

在開發(fā)過程中,根據(jù)需求和業(yè)務的不同經(jīng)常會有很多場景需要用到不同特性的定時任務,針對這些場景,這里提供不同的一個實現(xiàn)思路。定時任務可能需要的特性如下:

  • 多線程執(zhí)行:即一個定時任務是需要多線程去跑的,因為一個線程太慢了
  • 分布式執(zhí)行:在多線程的基礎(chǔ)上,用多臺機器的算力去執(zhí)行一個定時任務
  • 動態(tài)時間的定時任務:即定時任務的開始時間是不確定的
  • 連續(xù)上下文多線程定時任務:在使用多線程執(zhí)行定時任務的時候,嚴格按照任務的順序來執(zhí)行,即任務ABC,多線程執(zhí)行完A,然后再執(zhí)行B和C,不能存在A還有沒跑完的線程,B已經(jīng)開始的情況。
  • 可暫停繼續(xù)的定時任務:即一個任務執(zhí)行了一半,可以暫停后繼續(xù)運行。

針對以上的幾種特性,這里講一講相對簡單的實現(xiàn)方式

不同定時任務特性對應的實現(xiàn)方式

多線程執(zhí)行

多線程執(zhí)行相對來說是個比較簡單的需求,只需要定時任務觸發(fā)的時候,使用線程池去執(zhí)行任務,在springboot中,只需要使用@Async注解就行了。

//定時任務代碼
@Scheduled(fixedDelay = 60000)
    public void doSomeThing() {
        servive.doA();
    }
-------------------------------------------
//執(zhí)行定時任務邏輯代碼
@Service
public class Service(){
    @Async("A-config")
    public void doA(){
        //這里執(zhí)行邏輯省略
    }
}
-------------------------------------------
@Bean("updateById")
    public Executor updateById() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心線程數(shù):線程池創(chuàng)建時候初始化的線程數(shù)
        executor.setCorePoolSize(64);
        // 最大線程數(shù):線程池最大的線程數(shù),只有在緩沖隊列滿了之后才會申請超過核心線程數(shù)的線程
        executor.setMaxPoolSize(128);
        // 緩沖隊列:用來緩沖執(zhí)行任務的隊列
        executor.setQueueCapacity(500);
        // 允許線程的空閑時間60秒:當超過了核心線程之外的線程在空閑時間到達之后會被銷毀
        executor.setKeepAliveSeconds(60);
        // 線程池名的前綴:設(shè)置好了之后可以方便我們定位處理任務所在的線程池
        executor.setThreadNamePrefix("do-somthing-");
        // 緩沖隊列滿了之后的拒絕策略:這里調(diào)用主線程執(zhí)行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.initialize();
        return executor;
    }

分布式執(zhí)行

一般分布式定時任務主要是兩個問題,一個是觸發(fā),一個是分發(fā)。觸發(fā)需要考慮到只能有一個觸發(fā)成功,需要根據(jù)定時任務的間隔,指定合理的競爭策略,比如每日定時任務,那就用當日凌晨當key,利用redis的setnx原子操作來競爭。 然后就是分發(fā)問題,一般任務觸發(fā)后,利用多臺機分布式執(zhí)行定時任務,由一臺機觸發(fā)后,把任務分發(fā)到中間件中,然后多臺機器的服務去消費這些任務,這個中間件一般是隊列或者redis或者數(shù)據(jù)庫。

動態(tài)時間的定時任務

當需要在一個不確定的時間去執(zhí)行任務,比如我需要定時任務開啟一場折扣活動,而這個開啟時間取決于業(yè)務的其他條件出發(fā),這個開始時間會在某一個業(yè)務時刻存入數(shù)據(jù)庫或者reids,那就需要一個任務觸發(fā)檢測器了,可以跑一個1s為間隔的定時任務,每秒鐘都檢查一次這個任務是否需要執(zhí)行或者是否到了執(zhí)行時間,如果需要執(zhí)行就立刻執(zhí)行相應的任務邏輯。

連續(xù)上下文多線程定時任務

實際業(yè)務場景經(jīng)常會有這種情況,我需要連續(xù)的執(zhí)行A->B->C這三個任務,一定要按嚴格的順序執(zhí)行,如果我給這三個任務分別設(shè)置三個執(zhí)行時間,那后續(xù)任務如果超時或者執(zhí)行時間超過預期,就有可能出現(xiàn)B任務在A沒結(jié)束就執(zhí)行。所以只能按同一個定時任務觸發(fā)來執(zhí)行。而這時候我又需要多線程來提高效率。所以這個場景的重點在于,子任務結(jié)束的判定也就是線程執(zhí)行完畢的判斷。這里有種很簡單的實現(xiàn)方式。

實現(xiàn)這個場景的基本思路就是,在執(zhí)行任務A時候創(chuàng)建線程池去執(zhí)行A任務邏輯,然后分發(fā)完之后,shutdown線程池,調(diào)用線程池的awaitTermination方法去阻塞等待線程所有執(zhí)行完畢。這個方法結(jié)束后,自然所有A任務就執(zhí)行完了,銷毀線程池后執(zhí)行任務B,再創(chuàng)建新的線程池來執(zhí)行任務B,以此類推,這樣既用了多線程執(zhí)行速度的優(yōu)點又保證了任務的執(zhí)行順序。當然分布式用隊列和消費者來做的話,就更簡單,只需要監(jiān)控隊列的已消費和待發(fā)送以及消費完成數(shù)量,就知道任務是否完全結(jié)束。以下是多線程上下文任務的一個實現(xiàn)代碼

//創(chuàng)建線程池A,這里線程池改造過可以指定名字
NamedThreadPoolExecutor APool =
                new NamedThreadPoolExecutor(
                        32,
                        128,
                        60,
                        TimeUnit.SECONDS,
                        new LinkedBlockingQueue<>(5),
                        new ThreadPoolExecutor.CallerRunsPolicy(),
                        this.getClass().getSimpleName());
-------------------------------------------------------------
//這里拿到任務后,把任務都丟到線程池里去執(zhí)行
List<Object> taskA = getTask();
for(Object task:taskA){
    APool.execute(new CommonRunable(task));
}
//這里調(diào)用shutdown和awaitTermination,并設(shè)置最大超時,在方法執(zhí)行完后就表示任務A已經(jīng)完全執(zhí)行完了
APool.shutdown();
APool.awaitTermination(Long.MAX_VALUE,TimeUnit.NANOSECONDS);
//然后這里A已經(jīng)全部執(zhí)行完了,開始執(zhí)行B
NamedThreadPoolExecutor BPool =
                new NamedThreadPoolExecutor(
                        32,
                        128,
                        60,
                        TimeUnit.SECONDS,
                        new LinkedBlockingQueue<>(5),
                        new ThreadPoolExecutor.CallerRunsPolicy(),
                        this.getClass().getSimpleName());
List<Object> taskB = getTask();
for(Object task:taskB){
    BPool.execute(new CommonRunable(task));
}
//這里調(diào)用shutdown和awaitTermination,并設(shè)置最大超時,在方法執(zhí)行完后就表示任務B已經(jīng)完全執(zhí)行完了,繼續(xù)執(zhí)行后面的任務
BPool.shutdown();
BPool.awaitTermination(Long.MAX_VALUE,TimeUnit.NANOSECONDS);


//繼續(xù)執(zhí)行C任務
...

可暫停并重新開始的定時任務

實現(xiàn)一個可暫停并重新開始的定時任務,首先得考慮場景,如果這個暫停是主動暫停,那需要把這個任務執(zhí)行的進度和一些中間數(shù)據(jù)存入中間件或者內(nèi)存,然后再次開始的時候讀取這些中間數(shù)據(jù)就行了。如果這個暫停的場景包含被動暫停,比如任務中斷,或者進程掛了,那就需要在任務一開始就把中間數(shù)據(jù)和執(zhí)行進度都使用中間件存儲,再次開始的時候會直接從中間件讀取任務。一般來說,這里的中間件會選擇redis,像java中一些list或者set數(shù)據(jù)都是很方便存儲和讀取的。

到此這篇關(guān)于Java中定時任務的全方位場景實現(xiàn)思路分析的文章就介紹到這了,更多相關(guān)Java定時任務內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Springboot配置過濾器實現(xiàn)過程解析

    Springboot配置過濾器實現(xiàn)過程解析

    這篇文章主要介紹了Springboot配置過濾器實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • JVM代碼運行邏輯解讀

    JVM代碼運行邏輯解讀

    這篇文章主要介紹了JVM代碼運行邏輯,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • 關(guān)于JSON解析中獲取不存在的key問題

    關(guān)于JSON解析中獲取不存在的key問題

    這篇文章主要介紹了關(guān)于JSON解析中獲取不存在的key問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • java中常用的排序方法

    java中常用的排序方法

    今天給大家介紹一下,java中常用的排序方法。
    2013-04-04
  • Eclipse導出安卓apk文件的圖文教程

    Eclipse導出安卓apk文件的圖文教程

    這篇文章主要為大家詳細介紹了Eclipse導出安卓apk文件的圖文教程,以圖文結(jié)合的方式為大家分享了Eclipse是如何導出安卓apk文件的步驟,感興趣的小伙伴們可以參考一下
    2016-06-06
  • 多線程_解決Runnable接口無start()方法的情況

    多線程_解決Runnable接口無start()方法的情況

    這篇文章主要介紹了多線程_解決Runnable接口無start()方法的情況,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Maven繼承與聚合詳解及作用介紹

    Maven繼承與聚合詳解及作用介紹

    繼承關(guān)系中,分為父模塊與子模塊,父模塊也被稱為 parent 模塊,子模塊會繼承父模塊的依賴,父模塊中也可以設(shè)置依賴管理器,供子模塊選擇是否需要某些依賴
    2022-08-08
  • java DecimalFormat常用方法詳解

    java DecimalFormat常用方法詳解

    這篇文章主要為大家詳細介紹了java DecimalFormat的常用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • Java設(shè)計模式之觀察者模式

    Java設(shè)計模式之觀察者模式

    本文詳細講解了Java設(shè)計模式之觀察者模式,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • idea?springboot?jdk?maven版本兼容關(guān)系(最新推薦)

    idea?springboot?jdk?maven版本兼容關(guān)系(最新推薦)

    文章總結(jié)了SpringBoot、JDK、Maven和IntelliJIDEA之間的版本兼容性推薦,幫助開發(fā)者避免版本沖突和“版本地獄”,建議使用SpringBoot?3.3和JDK?21進行新項目開發(fā),使用SpringBoot?2.7和JDK?17進行企業(yè)穩(wěn)定項目開發(fā),感興趣的朋友跟隨小編一起看看吧
    2025-12-12

最新評論

灵璧县| 宁阳县| 鄯善县| 阳曲县| 蕉岭县| 习水县| 石阡县| 栾城县| 信丰县| 准格尔旗| 马关县| 翁牛特旗| 蒙阴县| 河曲县| 迁安市| 武安市| 桐庐县| 淮北市| 宜昌市| 丰城市| 莲花县| 辉县市| 桐柏县| 横峰县| 阳谷县| 贞丰县| 柘城县| 鹤山市| 海丰县| 尼木县| 江北区| 界首市| 农安县| 甘谷县| 临潭县| 舞钢市| 阳西县| 灵石县| 汉沽区| 克拉玛依市| 英德市|