源碼篇-ScheduledThreadPoolExecutor之執(zhí)行任務(wù)

一帕棉、schedule

public ScheduledFuture<?> schedule(Runnable command,
                                   long delay,
                                   TimeUnit unit) {
    if (command == null || unit == null)
        throw new NullPointerException();
    RunnableScheduledFuture<?> t = decorateTask(command,
        new ScheduledFutureTask<Void>(command, null,
                                      triggerTime(delay, unit)));
    delayedExecute(t);
    return t;
}


public <V> ScheduledFuture<V> schedule(Callable<V> callable,
                                       long delay,
                                       TimeUnit unit) {
    if (callable == null || unit == null)
        throw new NullPointerException();
    RunnableScheduledFuture<V> t = decorateTask(callable,
        new ScheduledFutureTask<V>(callable,
                                   triggerTime(delay, unit)));
    delayedExecute(t);
    return t;
}
  • 不同的地方在于一個(gè)傳入的是Runnable類型香伴,一個(gè)傳入的是Callable<V>類型即纲,但是Runnable類型最終也會(huì)轉(zhuǎn)為Callable類型
  • triggerTime是根據(jù)delay計(jì)算任務(wù)的執(zhí)行時(shí)間
private void delayedExecute(RunnableScheduledFuture<?> task) {
    // 如果線程池關(guān)閉了低斋,拒絕任務(wù)
    if (isShutdown())
        reject(task);
    else {
        // 將任務(wù)加入到隊(duì)列
        super.getQueue().add(task);
        // 再判斷線程池狀態(tài)
        if (isShutdown() &&
            !canRunInCurrentRunState(task.isPeriodic()) &&
            remove(task))
            task.cancel(false);
        // 啟動(dòng)任務(wù)
        else
            ensurePrestart();
    }
}

void ensurePrestart() {
    // 獲取工作線程數(shù)
    int wc = workerCountOf(ctl.get());
    // 啟動(dòng)核心線程
    if (wc < corePoolSize)
        // 因?yàn)檫@里是定時(shí)任務(wù)膊畴,所以這里firstTask為null
        addWorker(null, true);
    // 啟動(dòng)非核心線程
    else if (wc == 0)
        addWorker(null, false);
}
  • 根據(jù)線程池狀態(tài)判斷是否取消任務(wù)
  • Worker只是啟動(dòng)線程病游,最終執(zhí)行任務(wù)還是ScheduledFutureTask#run
public void run() {
    // 判斷是不是周期性任務(wù),period != 0 就是周期性任務(wù)
    boolean periodic = isPeriodic();
    // 根據(jù)線程池狀態(tài)判斷是否需要取消任務(wù)
    if (!canRunInCurrentRunState(periodic))
        cancel(false);
    // 如果是不是周期性任務(wù)买猖,執(zhí)行直接
    else if (!periodic)
        ScheduledFutureTask.super.run();
    // 如果是周期性任務(wù),需要重置狀態(tài)
    else if (ScheduledFutureTask.super.runAndReset()) {
        // 設(shè)置下一次執(zhí)行的時(shí)間
        setNextRunTime();
        // 重新添加任務(wù)
        reExecutePeriodic(outerTask);
    }
}

二飞主、scheduleAtFixedRate與scheduleWithFixedDelay

public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                              long initialDelay,
                                              long period,
                                              TimeUnit unit) {
    if (command == null || unit == null)
        throw new NullPointerException();
    if (period <= 0)
        throw new IllegalArgumentException();
    ScheduledFutureTask<Void> sft =
        new ScheduledFutureTask<Void>(command,
                                      null,
                                      triggerTime(initialDelay, unit),
                                      unit.toNanos(period));
    RunnableScheduledFuture<Void> t = decorateTask(command, sft);
    sft.outerTask = t;
    delayedExecute(t);
    return t;
}


public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                 long initialDelay,
                                                 long delay,
                                                 TimeUnit unit) {
    if (command == null || unit == null)
        throw new NullPointerException();
    if (delay <= 0)
        throw new IllegalArgumentException();
    ScheduledFutureTask<Void> sft =
        new ScheduledFutureTask<Void>(command,
                                      null,
                                      triggerTime(initialDelay, unit),
                                      unit.toNanos(-delay));
    RunnableScheduledFuture<Void> t = decorateTask(command, sft);
    sft.outerTask = t;
    delayedExecute(t);
    return t;
}
  • scheduleAtFixedRate傳入的period是正數(shù)碌识,scheduleWithFixedDelay傳入的period是負(fù)數(shù)
private void setNextRunTime() {
    long p = period;
    if (p > 0)
        time += p;
    else
        time = triggerTime(-p);
}

long triggerTime(long delay) {
    return now() +
        ((delay < (Long.MAX_VALUE >> 1)) ? delay : overflowFree(delay));
}
  • 由于scheduleAtFixedRate傳入的period為正數(shù)丸冕,所以下一個(gè)任務(wù)的執(zhí)行時(shí)間是相對(duì)上個(gè)任務(wù)的開(kāi)始時(shí)間
  • 由于scheduleWithFixedDelay傳入的period為負(fù)數(shù)薛窥,所以下一個(gè)任務(wù)的執(zhí)行時(shí)間是相對(duì)上個(gè)任務(wù)的結(jié)束時(shí)間
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末诅迷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子趟畏,更是在濱河造成了極大的恐慌滩租,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異技即,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)而叼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門液荸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)埃难,“玉大人涤久,你說(shuō)我怎么就攤上這事忍弛。” “怎么了蔗彤?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵然遏,是天一觀的道長(zhǎng)吧彪。 經(jīng)常有香客問(wèn)我,道長(zhǎng)秧倾,這世上最難降的妖魔是什么那先? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任赡艰,我火速辦了婚禮,結(jié)果婚禮上揖闸,老公的妹妹穿的比我還像新娘楔壤。我一直安慰自己惯驼,他們只是感情好递瑰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布抖部。 她就那樣靜靜地躺著慎颗,像睡著了一般言询。 火紅的嫁衣襯著肌膚如雪傲宜。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,541評(píng)論 1 305
  • 那天辆憔,我揣著相機(jī)與錄音报嵌,去河邊找鬼。 笑死腕巡,一個(gè)胖子當(dāng)著我的面吹牛血筑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播梆砸,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼帖世,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼沸枯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起哪轿,我...
    開(kāi)封第一講書(shū)人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤窃诉,失蹤者是張志新(化名)和其女友劉穎赤套,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體宣脉,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡塑猖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年羊苟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猿妈。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡彭则,死狀恐怖俯抖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芬萍,我是刑警寧澤柬祠,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布负芋,位于F島的核電站旧蛾,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏锨天。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一搂赋、第九天 我趴在偏房一處隱蔽的房頂上張望厂镇。 院中可真熱鬧,春花似錦酌媒、人聲如沸迄靠。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)抽米。三九已至,卻和暖如春是目,著一層夾襖步出監(jiān)牢的瞬間懊纳,已是汗流浹背亡容。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工闺兢, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人阱佛。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓凑术,卻偏偏與公主長(zhǎng)得像淮逊,于是被迫代替她去往敵國(guó)和親扶踊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容