黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

Java 線程池框架核心代碼分析


多線程編程中,為每個任務分配一個線程是不現(xiàn)實的,線程創(chuàng)建的開銷和資源消耗都是很高的。線程池應運而生,成為我們管理線程的利器。Java 通過Executor接口,提供了一種標準的方法將任務的提交過程和執(zhí)行過程解耦開來,并用Runnable表示任務。

下面,我們來分析一下 Java 線程池框架的實現(xiàn)ThreadPoolExecutor。

下面的分析基于JDK1.7

生命周期

ThreadPoolExecutor中,使用CAPACITY的高3位來表示運行狀態(tài),分別是:

1.RUNNING:接收新任務,并且處理任務隊列中的任務

2.SHUTDOWN:不接收新任務,但是處理任務隊列的任務

3.STOP:不接收新任務,不出來任務隊列,同時中斷所有進行中的任務

4.TIDYING:所有任務已經(jīng)被終止,工作線程數(shù)量為 0,到達該狀態(tài)會執(zhí)行terminated()

5.TERMINATEDterminated()執(zhí)行完畢

ThreadPoolExecutor中用原子類來表示狀態(tài)位

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

 

線程池模型

核心參數(shù)

1.corePoolSize:最小存活的工作線程數(shù)量(如果設置allowCoreThreadTimeOut,那么該值為 0)

2.maximumPoolSize:最大的線程數(shù)量,受限于CAPACITY

3.keepAliveTime:對應線程的存活時間,時間單位由TimeUnit指定

4.workQueue:工作隊列,存儲待執(zhí)行的任務

5.RejectExecutionHandler:拒絕策略,線程池滿后會觸發(fā)

線程池的最大容量CAPACITY中的前三位用作標志位,也就是說工作線程的最大容量為(2^29)-1

四種模型

1.CachedThreadPool:一個可緩存的線程池,如果線程池的當前規(guī)模超過了處理需求時,那么將回收空閑的線程,當需求增加時,則可以添加新的線程,線程池的規(guī)模不存在任何的限制。

2.FixedThreadPool:一個固定大小的線程池,提交一個任務時就創(chuàng)建一個線程,直到達到線程池的最大數(shù)量,這時線程池的大小將不再變化。

3.SingleThreadPool:一個單線程的線程池,它只有一個工作線程來執(zhí)行任務,可以確保按照任務在隊列中的順序來串行執(zhí)行,如果這個線程異常結束將創(chuàng)建一個新的線程來執(zhí)行任務。

4.ScheduledThreadPool:一個固定大小的線程池,并且以延遲或者定時的方式來執(zhí)行任務,類似于Timer。

執(zhí)行任務 execute

核心邏輯:

1.當前線程數(shù)量 < corePoolSize,直接開啟新的核心線程執(zhí)行任務addWorker(command, true)

2.當前線程數(shù)量 >= corePoolSize,且任務加入工作隊列成功

(1)檢查線程池當前狀態(tài)是否處于RUNNING

(2)如果否,則拒絕該任務

(3)如果是,判斷當前線程數(shù)量是否為 0,如果為 0,就增加一個工作線程。

3.開啟普通線程執(zhí)行任務addWorker(command, false),開啟失敗就拒絕該任務

從上面的分析可以總結出線程池運行的四個階段:

1.poolSize < corePoolSize 且隊列為空,此時會新建線程來處理提交的任務

2.poolSize == corePoolSize,此時提交的任務進入工作隊列,工作線程從隊列中獲取任務執(zhí)行,此時隊列不為空且未滿。

3.poolSize == corePoolSize,并且隊列已滿,此時也會新建線程來處理提交的任務,但是poolSize < maxPoolSize

4.poolSize == maxPoolSize,并且隊列已滿,此時會觸發(fā)拒絕策略

拒絕策略

前面我們提到任務無法執(zhí)行會被拒絕,RejectedExecutionHandler是處理被拒絕任務的接口。下面是四種拒絕策略。

1.AbortPolicy:默認策略,終止任務,拋出RejectedException

2.CallerRunsPolicy:在調用者線程執(zhí)行當前任務,不拋異常

3.DiscardPolicy: 拋棄策略,直接丟棄任務,不拋異常

4.DiscardOldersPolicy:拋棄老的任務,執(zhí)行當前任務,不拋異常

線程池中的 Worker

Worker繼承了AbstractQueuedSynchronizer和Runnable,前者給Worker提供鎖的功能,后者執(zhí)行工作線程的主要方法runWorker(Worker w)(從任務隊列撈任務執(zhí)行)。Worker 引用存在workers集合里面,用mainLock守護。

private final ReentrantLock mainLock = new ReentrantLock();
private final HashSet workers = new HashSet();

 

核心函數(shù) runWorker

下面是簡化的邏輯,注意:每個工作線程的run都執(zhí)行下面的函數(shù)

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    while (task != null || (task = getTask()) != null) {
        w.lock();
        beforeExecute(wt, task);
        task.run();
        afterExecute(task, thrown);
        w.unlock();
    }
    processWorkerExit(w, completedAbruptly);
}

 

1.getTask()中獲取任務

2.鎖住 worker

3.執(zhí)行beforeExecute(wt, task),這是ThreadPoolExecutor提供給子類的擴展方法

4.運行任務,如果該worker有配置了首次任務,則先執(zhí)行首次任務且只執(zhí)行一次。

5.執(zhí)行afterExecute(task, thrown);

6.解鎖 worker

7.如果獲取到的任務為 null,關閉 worker

獲取任務 getTask

線程池內部的任務隊列是一個阻塞隊列,具體實現(xiàn)在構造時傳入。

private final BlockingQueue workQueue;

 

getTask()從任務隊列中獲取任務,支持阻塞和超時等待任務,四種情況會導致返回null,讓worker關閉。

1.現(xiàn)有的線程數(shù)量超過最大線程數(shù)量

2.線程池處于STOP狀態(tài)

3.線程池處于SHUTDOWN狀態(tài)且工作隊列為空

4.線程等待任務超時,且線程數(shù)量超過保留線程數(shù)量

核心邏輯:根據(jù)timed在阻塞隊列上超時等待或者阻塞等待任務,等待任務超時會導致工作線程被關閉。

timed = allowCoreThreadTimeOut || wc > corePoolSize;
Runnable r = timed ?
    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
    workQueue.take();

 

在以下兩種情況下等待任務會超時:

1.允許核心線程等待超時,即allowCoreThreadTimeOut(true)

2.當前線程是普通線程,此時wc > corePoolSize

工作隊列使用的是BlockingQueue,這里就不展開了,后面再寫一篇詳細的分析。

總結

1.ThreadPoolExecutor基于生產(chǎn)者-消費者模式,提交任務的操作相當于生產(chǎn)者,執(zhí)行任務的線程相當于消費者。

2.Executors提供了四種基于ThreadPoolExecutor構造線程池模型的方法,除此之外,我們還可以直接繼承ThreadPoolExecutor,重寫beforeExecute和afterExecute方法來定制線程池任務執(zhí)行過程。

3.使用有界隊列還是無界隊列需要根據(jù)具體情況考慮,工作隊列的大小和線程的數(shù)量也是需要好好考慮的。

4.拒絕策略推薦使用CallerRunsPolicy,該策略不會拋棄任務,也不會拋出異常,而是將任務回退到調用者線程中執(zhí)行。

更多Java培訓,Java視頻,Java教程盡在動力節(jié)點Java培訓,關注動力節(jié)點官方微信,獲得一手Java全新知識。

 

上一篇:程序員必須是年輕人嗎?
下一篇:用Java日志來寫詩

開班信息

主站蜘蛛池模板: 亚洲欧美日韩高清专区一区 | 国产成人无精品久久久 | 国产精品久久久亚洲第一牛牛 | 99精品影视 | a黄视频| 日韩精品网站 | 精品偷国情拍在线视频 | 免费看黄a级毛片 | 久久96国产精品 | 国产精品久久久久乳精品爆 | 国产精品一卡二卡三卡 | a国产片 | 91.xxx.高清在线| 全免费一级毛片在线播放 | 色婷婷狠狠 | 一区二区三区高清在线观看 | 国产一国产一级毛片视频在线 | 人人爽人人看 | 天天做天天操 | 看真人视频a级毛片 | 99草在线| 天天看片天天爽_免费播放 天天看片夜夜爽 | 国产麻豆精品免费视频 | 综合亚洲欧美日韩一区二区 | 欧美3区 | 黑人巨大videos极度另类 | 欧美乱人伦中文字幕在线不卡 | 亚洲国产一级毛片 | 鲁丝片一区二区三区免费 | a级精品九九九大片免费看 a级精品国产片在线观看 | 国产亚洲精品精品国产亚洲综合 | 日韩欧美一区二区三区视频 | 性放荡一级小说 | 国产干美女 | 免费午夜网站 | 亚洲色图综合在线 | 久草网免费 | 欧美人与牲动交a欧美精品 欧美人与日本人xx在线视频 | 国产欧美激情一区二区三区-老狼 | 黄网在线看 | 一区二区不卡不卡一卡 |