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

資訊專欄INFORMATION COLUMN

周期性線程池與主要源碼解析

馬龍駒 / 1425人閱讀

摘要:今天給大家介紹下周期性線程池的使用和重點源碼剖析。用來處理延時任務(wù)或定時任務(wù)定時線程池類的類結(jié)構(gòu)圖接收類型的任務(wù),是線程池調(diào)度任務(wù)的最小單位。周期性線程池任務(wù)的提交方式周期性有三種提交的方式。

之前學(xué)習(xí)ThreadPool的使用以及源碼剖析,并且從面試的角度去介紹知識點的解答。今天給大家介紹下周期性線程池的使用和重點源碼剖析。
ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor:用來處理延時任務(wù)或定時任務(wù)
定時線程池類的類結(jié)構(gòu)圖

ScheduledThreadPoolExecutor接收ScheduleFutureTask類型的任務(wù),是線程池調(diào)度任務(wù)的最小單位。
它采用DelayQueue存儲等待的任務(wù):
1、DelayQueue內(nèi)部封裝成一個PriorityQueue,它會根據(jù)time的先后時間順序,如果time相同則根絕sequenceNumber排序;
2、DelayQueue是無界隊列;

ScheduleFutureTask

接收的參數(shù):

private final long sequenceNumber;//任務(wù)的序號
private long time;//任務(wù)開始的時間
private final long period;//任務(wù)執(zhí)行的時間間隔

工作線程的的執(zhí)行過程:
工作線程會從DelayQueue取出已經(jīng)到期的任務(wù)去執(zhí)行;
執(zhí)行結(jié)束后重新設(shè)置任務(wù)的到期時間,再次放回DelayQueue;

ScheduledThreadPoolExecutor會把待執(zhí)行的任務(wù)放到工作隊列DelayQueue中,DelayQueue封裝了一個PriorityQueue,PriorityQueue會對隊列中的ScheduledFutureTask進(jìn)行排序,具體的排序算法實現(xiàn)如下:

public int compareTo(Delayed other) {
    if (other == this) // compare zero if same object
        return 0;
    if (other instanceof ScheduledFutureTask) {
        ScheduledFutureTask x = (ScheduledFutureTask)other;
        //首先按照time排序,time小的排到前面,time大的排到后面
        long diff = time - x.time;
        if (diff < 0)
            return -1;
        else if (diff > 0)
            return 1;
        //time相同,按照sequenceNumber排序;
        //sequenceNumber小的排在前面,sequenceNumber大的排在后面 
        else if (sequenceNumber < x.sequenceNumber)
            return -1;
        else
            return 1;
    }
    long diff = getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS);
    return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
}

接下來看看ScheduledFutureTask的run方法實現(xiàn), run方法是調(diào)度task的核心,task的執(zhí)行實際上是run方法的執(zhí)行。

public void run() {
    //是否是周期性的
    boolean periodic = isPeriodic();
    //線程池是shundown狀態(tài)不支持處理新任務(wù),直接取消任務(wù)
    if (!canRunInCurrentRunState(periodic))
        cancel(false);
    //如果不需要執(zhí)行執(zhí)行周期性任務(wù),直接執(zhí)行run方法結(jié)束
    else if (!periodic)
        ScheduledFutureTask.super.run();
    //如果需要周期性執(zhí)行,則在執(zhí)行任務(wù)完成后,設(shè)置下一次執(zhí)行時間
    else if (ScheduledFutureTask.super.runAndReset()) {
        //設(shè)置下一次執(zhí)行該任務(wù)的時間
        setNextRunTime();
        //重復(fù)執(zhí)行該任務(wù)
        reExecutePeriodic(outerTask);
    }
}

run方法的執(zhí)行步驟:

1、如果線程池是shundown狀態(tài)不支持處理新任務(wù),直接取消任務(wù),否則步驟2;

2、如果不是周期性任務(wù),直接調(diào)用ScheduledFutureTask的run方法執(zhí)行,會設(shè)置執(zhí)行結(jié)果,然后直接返回,否則步驟3;

3、如果是周期性任務(wù),調(diào)用ScheduledFutureTask的runAndset方法執(zhí)行,不會設(shè)置執(zhí)行結(jié)果,然后直接返回,否則執(zhí)行步驟4和步驟5;

4、計算下一次執(zhí)行該任務(wù)的時間;

5、重復(fù)執(zhí)行該任務(wù);

接下來看下reExecutePeriodic方法的執(zhí)行步驟:

void reExecutePeriodic(RunnableScheduledFuture task) {
    if (canRunInCurrentRunState(true)) {
        super.getQueue().add(task);
        if (!canRunInCurrentRunState(true) && remove(task))
            task.cancel(false);
        else
            ensurePrestart();
    }
}

由于已經(jīng)執(zhí)行過一次周期性任務(wù),所以不會reject當(dāng)前任務(wù),同時傳入的任務(wù)一定是周期性任務(wù)。

周期性線程池任務(wù)的提交方式

周期性有三種提交的方式:schedule、sceduleAtFixedRate、schedlueWithFixedDelay。下面從使用和源碼兩個方面進(jìn)行說明,首先是如果提交任務(wù):

pool.schedule(new Runnable() {
    @Override
    public void run() {
        System.out.println("延遲執(zhí)行");
    }
},1, TimeUnit.SECONDS);

/**
 * 這個執(zhí)行周期是固定,不管任務(wù)執(zhí)行多長時間,每過3秒中就會產(chǎn)生一個新的任務(wù)
 */
pool.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        //這個業(yè)務(wù)邏輯需要很長的時間,超過了3秒
        System.out.println("重復(fù)執(zhí)行");
    }
},1,3,TimeUnit.SECONDS);

pool.shutdown();

/**
 * 假如run方法30min后執(zhí)行完成,然后間隔3秒,再周期性執(zhí)行下一個任務(wù)
 */
pool.scheduleWithFixedDelay(new Runnable() {
    @Override
    public void run() {
        //30min
        System.out.println("重復(fù)執(zhí)行");
    }
},1,3,TimeUnit.SECONDS);

知道了如何提交周期性任務(wù),接下來源碼是如何執(zhí)行的,首先是schedule方法,該方法是指任務(wù)在指定延遲時間到達(dá)后觸發(fā),只會執(zhí)行一次。

public ScheduledFuture schedule(Runnable command,
                                   long delay,
                                   TimeUnit unit) {
    if (command == null || unit == null)
        throw new NullPointerException();
    //把任務(wù)封裝成ScheduledFutureTask,之后調(diào)用decorateTask進(jìn)行包裝;
    //decorateTask方法是空方法,留給用戶去實現(xiàn)的;
    RunnableScheduledFuture t = decorateTask(command,
        new ScheduledFutureTask(command, null,
                                      triggerTime(delay, unit)));
    //包裝好任務(wù)之后,進(jìn)行任務(wù)的提交                                  
    delayedExecute(t);
    return t;
}

任務(wù)提交方法:

private void delayedExecute(RunnableScheduledFuture task) {
    //如果線程池不是RUNNING狀態(tài),則使用拒絕策略把提交任務(wù)拒絕掉
    if (isShutdown())
        reject(task);
    else {
        //與ThreadPoolExecutor不同,這里直接把任務(wù)加入延遲隊列
        super.getQueue().add(task);
        //如果當(dāng)前狀態(tài)無法執(zhí)行任務(wù),則取消
        if (isShutdown() &&
            !canRunInCurrentRunState(task.isPeriodic()) &&
            remove(task))
            task.cancel(false);
        else
        //和ThreadPoolExecutor不一樣,corePoolSize沒有達(dá)到會增加Worker;
        //增加Worker,確保提交的任務(wù)能夠被執(zhí)行
            ensurePrestart();
    }
}
還沒關(guān)注我的公眾號?

掃文末二維碼關(guān)注公眾號【小強(qiáng)的進(jìn)階之路】可領(lǐng)取如下:

學(xué)習(xí)資料: 1T視頻教程:涵蓋Javaweb前后端教學(xué)視頻、機(jī)器學(xué)習(xí)/人工智能教學(xué)視頻、Linux系統(tǒng)教程視頻、雅思考試視頻教程;

100多本書:包含C/C++、Java、Python三門編程語言的經(jīng)典必看圖書、LeetCode題解大全;

軟件工具:幾乎包括你在編程道路上的可能會用到的大部分軟件;

項目源碼:20個JavaWeb項目源碼。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/76284.html

相關(guān)文章

  • Java多線程學(xué)習(xí)(八)線程池與Executor 框架

    摘要:一使用線程池的好處線程池提供了一種限制和管理資源包括執(zhí)行一個任務(wù)。每個線程池還維護(hù)一些基本統(tǒng)計信息,例如已完成任務(wù)的數(shù)量。通過重復(fù)利用已創(chuàng)建的線程降低線程創(chuàng)建和銷毀造成的消耗。使用無界隊列作為線程池的工作隊列會對線程池帶來的影響與相同。 歷史優(yōu)質(zhì)文章推薦: Java并發(fā)編程指南專欄 分布式系統(tǒng)的經(jīng)典基礎(chǔ)理論 可能是最漂亮的Spring事務(wù)管理詳解 面試中關(guān)于Java虛擬機(jī)(jvm)的問...

    cheng10 評論0 收藏0
  • Java 多線程(5):Fork/Join 型線程池與 Work-Stealing 算法

    摘要:時,標(biāo)準(zhǔn)類庫添加了,作為對型線程池的實現(xiàn)。類圖用來專門定義型任務(wù)完成將大任務(wù)分割為小任務(wù)以及合并結(jié)果的工作。 JDK 1.7 時,標(biāo)準(zhǔn)類庫添加了 ForkJoinPool,作為對 Fork/Join 型線程池的實現(xiàn)。Fork 在英文中有 分叉 的意思,而 Join 有 合并 的意思。ForkJoinPool 的功能也是如此:Fork 將大任務(wù)分叉為多個小任務(wù),然后讓小任務(wù)執(zhí)行,Join...

    IamDLY 評論0 收藏0
  • 2019 Android 高級面試題總結(jié)

    摘要:子線程往消息隊列發(fā)送消息,并且往管道文件寫數(shù)據(jù),主線程即被喚醒,從管道文件讀取數(shù)據(jù),主線程被喚醒只是為了讀取消息,當(dāng)消息讀取完畢,再次睡眠。因此的循環(huán)并不會對性能有過多的消耗。 說下你所知道的設(shè)計模式與使用場景 a.建造者模式: 將一個復(fù)雜對象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。 使用場景比如最常見的AlertDialog,拿我們開發(fā)過程中舉例,比如Camera...

    wums 評論0 收藏0
  • 【私有專區(qū) UDHost】私有專區(qū)價格:資源池與私有專區(qū)主機(jī)

    摘要:私有專區(qū)價格文檔中的價格以北京二可用區(qū)為例,其余可用區(qū)的價格可咨詢您的客戶經(jīng)理。資源池資源池支持按月以及按年付費暫不支持按需付費。價格列表如下核內(nèi)存磁盤定價元月定價元年私有專區(qū)主機(jī)私有專區(qū)主機(jī)生命周期與資源池一致,無收費項。實時文檔歡迎訪問私有專區(qū)價格文檔中的價格以北京二可用區(qū)E為例,其余可用區(qū)的價格可咨詢您的客戶經(jīng)理。1. 資源池資源池支持按月以及按年付費(暫不支持按需付費)。價格列表如下...

    Tecode 評論0 收藏0

發(fā)表評論

0條評論

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