Java線程池解析

前言

線程是稀缺資源碍遍,如果被無限制的創(chuàng)建定铜,不僅會消耗系統(tǒng)資源,還會降低系統(tǒng)的穩(wěn)定性怕敬,合理的使用線程池對線程進行統(tǒng)一分配揣炕、調優(yōu)和監(jiān)控,有以下好處:

  1. 降低資源消耗东跪;
  2. 提高響應速度畸陡;
  3. 提高線程的可管理性

線程池實現(xiàn)原理

如上圖所示,線程池的執(zhí)行分為4步

  1. workerCountOf()根據(jù)ctl的低29位(ctl高三位是線程池狀態(tài)位越庇,其余29位是線程池中的線程數(shù)量)罩锐,得到線程池的當前線程數(shù),如果線程數(shù)小于corePoolSize卤唉,則執(zhí)行addWorker方法創(chuàng)建新的線程執(zhí)行任務涩惑;否則執(zhí)行步驟2;(執(zhí)行這一步要獲取全局鎖)
  2. 線程池判斷工作隊列是否已滿桑驱。如果沒有滿則將新任務放入工作隊列竭恬。如果已滿,則進入步驟3熬的;
  3. 線程池判斷當前線程數(shù)是否大于maximumPoolSize痊硕,如果線程數(shù)小于maximumPoolSize,則創(chuàng)建新線程來處理任務(這一步需要獲取全局鎖)押框;
  4. 如果線程數(shù)超出maximumPoolSize岔绸,會調用reject方法處理任務;
public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    // 步驟1
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    // 步驟2
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        if (! isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    // 步驟3
    else if (!addWorker(command, false))
        // 步驟4
        reject(command);
}

線程池的構造

線程池構造函數(shù)如下:

public ThreadPoolExecutor(int corePoolSize,
        int maximumPoolSize,
        long keepAliveTime,
        TimeUnit unit,
        BlockingQueue<Runnable> workQueue,
        ThreadFactory threadFactory,
        RejectedExecutionHandler handler) {
    ...省略部分源碼
}
  1. corePoolSize
    線程池中的核心線程數(shù)橡伞,當提交一個任務時盒揉,線程池創(chuàng)建一個新線程執(zhí)行任務,直到當前線程數(shù)等于corePoolSize兑徘;如果當前線程數(shù)為corePoolSize刚盈,繼續(xù)提交的任務被保存到阻塞隊列中,等待被執(zhí)行挂脑;如果執(zhí)行了線程池的prestartAllCoreThreads()方法藕漱,線程池會提前創(chuàng)建并啟動所有核心線程欲侮。
  2. maximumPoolSize
    線程池中允許的最大線程數(shù)。如果當前阻塞隊列滿了肋联,且繼續(xù)提交任務威蕉,則創(chuàng)建新的線程執(zhí)行任務,前提是當前線程數(shù)小于maximumPoolSize橄仍;
  3. keepAliveTime
    線程空閑時的存活時間忘伞,即當線程沒有任務執(zhí)行時,繼續(xù)存活的時間沙兰;默認情況下,該參數(shù)只在線程數(shù)大于corePoolSize時才有用翘魄;
  4. unit
    keepAliveTime的單位鼎天;
  5. workQueue
    用來保存等待被執(zhí)行的任務的阻塞隊列,且任務必須實現(xiàn)Runable接口暑竟,在JDK中提供了如下阻塞隊列:
    (1)ArrayBlockingQueue:基于數(shù)組結構的有界阻塞隊列斋射,按FIFO排序任務;
    (2)LinkedBlockingQuene:基于鏈表結構的阻塞隊列但荤,按FIFO排序任務罗岖,吞吐量通常要高于ArrayBlockingQuene;
    (3)SynchronousQuene:一個不存儲元素的阻塞隊列腹躁,每個插入操作必須等到另一個線程調用移除操作桑包,否則插入操作一直處于阻塞狀態(tài),吞吐量通常要高于LinkedBlockingQuene纺非;
    (4)priorityBlockingQuene:具有優(yōu)先級的無界阻塞隊列哑了;
  6. threadFactory
    創(chuàng)建線程的工廠,通過自定義的線程工廠可以給每個新建的線程設置一個具有識別度的線程名烧颖。
  7. handler
    線程池的飽和策略弱左,當阻塞隊列滿了,且沒有空閑的工作線程炕淮,如果繼續(xù)提交任務拆火,必須采取一種策略處理該任務,線程池提供了4種策略:
    (1)AbortPolicy:直接拋出異常涂圆,默認策略们镜;
    (2)CallerRunsPolicy:用調用者所在的線程來執(zhí)行任務;
    (3)DiscardOldestPolicy:丟棄阻塞隊列中靠最前的任務乘综,并執(zhí)行當前任務憎账;
    (4)DiscardPolicy:直接丟棄任務;
    當然也可以根據(jù)應用場景實現(xiàn)RejectedExecutionHandler接口卡辰,自定義飽和策略胞皱,如記錄日志或持久化存儲不能處理的任務邪意。

關閉線程池

通過調用shutdownshutdownNow方法來關閉線程池。它們的原理是遍歷線程池中的工作線程反砌,逐個調用interrupt方法中斷線程雾鬼。它們的區(qū)別是 shutdownNow首先將線程池狀態(tài)設為STOP,然后嘗試停止所有正在執(zhí)行或暫停的工作線程宴树,并返回等待執(zhí)行任務的列表策菜,而shutdown只是將線程池狀態(tài)設為SHUTDOWN,然后中斷沒有執(zhí)行任務的工作線程酒贬。
只要調用其中一個又憨,isShutDown方法會返回true。當所有的線程都已關閉锭吨,才表示線程池關閉成功蠢莺,這是調用isTerminaed方法才會返回true宝泵。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芯侥,一起剝皮案震驚了整個濱河市呻引,隨后出現(xiàn)的幾起案子考蕾,更是在濱河造成了極大的恐慌祸憋,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肖卧,死亡現(xiàn)場離奇詭異蚯窥,居然都是意外死亡,警方通過查閱死者的電腦和手機喜命,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門沟沙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人壁榕,你說我怎么就攤上這事矛紫。” “怎么了牌里?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵颊咬,是天一觀的道長。 經(jīng)常有香客問我牡辽,道長喳篇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任态辛,我火速辦了婚禮麸澜,結果婚禮上,老公的妹妹穿的比我還像新娘奏黑。我一直安慰自己炊邦,他們只是感情好编矾,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著馁害,像睡著了一般窄俏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碘菜,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天凹蜈,我揣著相機與錄音忍啸,去河邊找鬼仰坦。 笑死,一個胖子當著我的面吹牛计雌,可吹牛的內(nèi)容都是我干的缎岗。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼白粉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鼠渺?” 一聲冷哼從身側響起鸭巴,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拦盹,沒想到半個月后鹃祖,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡普舆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年恬口,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沼侣。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡祖能,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蛾洛,到底是詐尸還是另有隱情养铸,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布轧膘,位于F島的核電站钞螟,受9級特大地震影響,放射性物質發(fā)生泄漏谎碍。R本人自食惡果不足惜鳞滨,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蟆淀。 院中可真熱鬧拯啦,春花似錦澡匪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至碱蒙,卻和暖如春荠瘪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赛惩。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工哀墓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人喷兼。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓篮绰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親季惯。 傳聞我的和親對象是個殘疾皇子吠各,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

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