ScheduledThreadPoolExecutor

ScheduledFutureTask

run

public void run() {
    // 首先判斷是否是周期性任務(wù)
    boolean periodic = isPeriodic();
    // 如果該任務(wù)不能再當(dāng)前的線程池狀態(tài)下運(yùn)行与境,那么取消任務(wù)
    if (!canRunInCurrentRunState(periodic))
        cancel(false);
    // 如果不是周期性任務(wù)验夯,那么該任務(wù)就是個(gè)普通的FutureTask,直接調(diào)用父類的run
    else if (!periodic)
        ScheduledFutureTask.super.run();
    // 到這里摔刁,說(shuō)明是周期性任務(wù)挥转,那么執(zhí)行且重置任務(wù)
    else if (ScheduledFutureTask.super.runAndReset()) {
        // 計(jì)算下個(gè)周期
        setNextRunTime();
        // 
        reExecutePeriodic(outerTask);
    }
}

reExecutePeriodic

void reExecutePeriodic(RunnableScheduledFuture<?> task) {   
    // 如果當(dāng)前線程池狀態(tài)允許執(zhí)行周期性任務(wù)
    if (canRunInCurrentRunState(true)) {
        // 將該任務(wù)重新再假如到任務(wù)列表中
        super.getQueue().add(task);
        // 如果現(xiàn)在線程池狀態(tài)又不允許了,那么從任務(wù)列表中移除該任務(wù)共屈,且取消執(zhí)行
        if (!canRunInCurrentRunState(true) && remove(task))
            task.cancel(false);
        else
            // 否則新增工作線程绑谣,worker會(huì)自己去拿任務(wù)
            ensurePrestart();
    }
}

delayedExecute

private void delayedExecute(RunnableScheduledFuture<?> task) {
    // 如果線程池已經(jīng)SHUTDOWN,那么執(zhí)行拒絕策略
    if (isShutdown())
        reject(task);
    else {
        // 將任務(wù)加到任務(wù)列表中
        super.getQueue().add(task);
        
        // 如果線程池是SHUTDOWN拗引,且任務(wù)不能再SHUTDOWN之后繼續(xù)執(zhí)行
        // 那么這個(gè)任務(wù)沒(méi)有存在的意義借宵,從隊(duì)列中刪除該任務(wù),并嘗試取消任務(wù)執(zhí)行
        if (isShutdown() &&  
            !canRunInCurrentRunState(task.isPeriodic()) &&
            remove(task))
            task.cancel(false);
        else
            // 添加工作線程矾削,worker會(huì)自己去拿任務(wù)
            ensurePrestart();
    }
}

ensurePrestart

void ensurePrestart() {
    // 拿到工作線程數(shù)
    int wc = workerCountOf(ctl.get());
    // 如果小于核心線程數(shù)壤玫,那么增加工作線程,worker會(huì)自己去拿任務(wù)
    if (wc < corePoolSize)
        addWorker(null, true);
    else if (wc == 0)
        addWorker(null, false);
}

DelayedWorkQueue

offer

public boolean offer(Runnable x) {
    if (x == null)
        throw new NullPointerException();
    RunnableScheduledFuture<?> e = (RunnableScheduledFuture<?>)x;
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        int i = size;
        // 如果超過(guò)queue的長(zhǎng)度哼凯,那么擴(kuò)容
        if (i >= queue.length)
            grow();
        // 否則長(zhǎng)度加一
        size = i + 1;
        // 如果當(dāng)前隊(duì)列為空垦细,那么該任務(wù)作為首節(jié)點(diǎn)
        if (i == 0) {
            queue[0] = e;
            setIndex(e, 0);
        // 否則做堆上浮的操作,將該任務(wù)放在二叉堆中合適的位置
        } else {
            siftUp(i, e);
        }
        // 經(jīng)過(guò)上面的操作挡逼,如果當(dāng)前隊(duì)列的首節(jié)點(diǎn)是當(dāng)前任務(wù)括改,那么喚醒一個(gè)等待線程開始處理
        // 如果首節(jié)點(diǎn),不是當(dāng)前任務(wù)的話,那么這里只是插入嘱能,不做喚醒
        if (queue[0] == e) {
            leader = null;
            available.signal();
        }
    } finally {
        lock.unlock();
    }
    return true;
}

take

public RunnableScheduledFuture<?> take() throws InterruptedException {
    final ReentrantLock lock = this.lock;
    // 先鎖隊(duì)列
    lock.lockInterruptibly();
    try {
        for (;;) {
            // 拿到首節(jié)點(diǎn)
            RunnableScheduledFuture<?> first = queue[0];
            // 如果首節(jié)點(diǎn)為空吝梅,那么等待,直到有任務(wù)為止
            // Leader-Follower pattern
            if (first == null)
                available.await();
            else {
                long delay = first.getDelay(NANOSECONDS);
                // 如果首節(jié)點(diǎn)已經(jīng)超時(shí)惹骂,說(shuō)明到了該任務(wù)的執(zhí)行時(shí)間了苏携,那么返回該任務(wù)
                if (delay <= 0)
                    return finishPoll(first);
                first = null; // don't retain ref while waiting
                // 如果leader不為空,說(shuō)明有其他線程在執(zhí)行任務(wù)对粪,那么這里無(wú)限等待
                if (leader != null)
                    available.await();
                else {
                    // 否則右冻,說(shuō)明leader現(xiàn)在是空擋
                    Thread thisThread = Thread.currentThread();
                    // 將當(dāng)前線程作為新的leader
                    leader = thisThread;
                    try {
                        // 等待任務(wù)
                        available.awaitNanos(delay);
                    } finally {
                        if (leader == thisThread)
                            leader = null;
                    }
                }
            }
        }
    } finally {
        if (leader == null && queue[0] != null)
            available.signal();
        lock.unlock();
    }
}

finishPoll

private RunnableScheduledFuture<?> finishPoll(RunnableScheduledFuture<?> f) {
    int s = --size;
    RunnableScheduledFuture<?> x = queue[s];
    queue[s] = null;
    if (s != 0)
        // 將最后節(jié)點(diǎn)放到堆頂,做堆下沉著拭,重新整理二叉堆
        siftDown(0, x);
    setIndex(f, -1);
    return f;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末纱扭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子儡遮,更是在濱河造成了極大的恐慌乳蛾,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肃叶,死亡現(xiàn)場(chǎng)離奇詭異十嘿,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)绩衷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門唇聘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人剥险,你說(shuō)我怎么就攤上這事”碇疲” “怎么了控乾?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)壤短。 經(jīng)常有香客問(wèn)我,道長(zhǎng)纳胧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任跑慕,我火速辦了婚禮核行,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘芝雪。我一直安慰自己婆赠,他們只是感情好佳励,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著妙黍,像睡著了一般瞧剖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上抓于,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天捉撮,我揣著相機(jī)與錄音,去河邊找鬼巾遭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛吼和,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播炫乓,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼厢岂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了塔粒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤船老,失蹤者是張志新(化名)和其女友劉穎圃酵,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體郭赐,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捌锭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拉盾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片豁状。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖夭禽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情讹躯,我是刑警寧澤凶异,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站酷麦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏沃饶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一糊肤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧馆揉,春花似錦、人聲如沸舷暮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)绩聘。三九已至,卻和暖如春凿菩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背叉庐。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工会喝, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留玩郊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓译红,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親耻陕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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