更新時(shí)間:2020-11-16 17:32:34 來源:動(dòng)力節(jié)點(diǎn) 瀏覽1750次
我們?cè)诠ぷ髦谢蚨嗷蛏俣际褂眠^線程池,但是為什么要使用線程池呢?從他的名字中我們就應(yīng)該知道,線程池使用了一種池化技術(shù),和很多其他池化技術(shù)一樣,都是為了更高效的利用資源,例如鏈接池,內(nèi)存池等等。那么,線程池的工作原理到底是怎樣的呢?
實(shí)際上,線程池是一種生產(chǎn)者 - 消費(fèi)者模式,線程池的使用方是生產(chǎn)者,線程池本身是消費(fèi)者。我們可以通過下面的代碼來理解線程池的工作原理。
public class ThreadPoolDemo {
//利用阻塞隊(duì)列實(shí)現(xiàn)生產(chǎn)者-消費(fèi)者模式
BlockingQueue
//保存內(nèi)部工作線程
List
private ThreadPoolDemo(int poolSize, BlockingQueue
this.workQueue = workQueue;
// 創(chuàng)建工作線程
for (int idx = 0; idx < poolSize; idx++) {
WorkerThread work = new WorkerThread();
work.start();
threads.add(work);
}
}
// 提交任務(wù)
public void execute(Runnable command) throws InterruptedException {
workQueue.put(command);
}
// 工作線程負(fù)責(zé)消費(fèi)任務(wù),并執(zhí)行任務(wù)
class WorkerThread extends Thread {
public void run() {
//循環(huán)取任務(wù)并執(zhí)行
while (true) {
Runnable task = null;
try {
task = workQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
assert task != null;
task.run();
}
}
}
public static void main(String[] args) throws InterruptedException {
BlockingQueue
new LinkedBlockingQueue<>(2);
// 創(chuàng)建線程池
ThreadPoolDemo pool = new ThreadPoolDemo(10, workQueue);
// 提交任務(wù)
pool.execute(()->{
System.out.println("hello world");
});
}
}
通過上面的Demo可見,線程池的創(chuàng)建都是通過ThreadPoolExecutor完成的,來看一下它的構(gòu)造方法。
# -> ThreadPoolExecutor構(gòu)造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
...
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
構(gòu)造方法聲明的一系列參數(shù)非常重要,理解了它們線程池的基本原理你就掌握了,我們來看看他們的具體含義:
corePoolSize 核心線程數(shù),除非設(shè)置核心線程超時(shí)(allowCoreThreadTimeOut),線程一直存活在線程池中,即使線程處于空閑狀態(tài)。
maximumPoolSize 線程池中允許存在的最大線程數(shù)。
workQueue 工作隊(duì)列,當(dāng)核心線程都處于繁忙狀態(tài)時(shí),將任務(wù)提交到工作隊(duì)列中。如果工作隊(duì)列也超過了容量,會(huì)去嘗試創(chuàng)建一個(gè)非核心線程執(zhí)行任務(wù)。
keepAliveTime 非核心線程處理空閑狀態(tài)的最長時(shí)間,超過該值線程則會(huì)被回收。
threadFactory 線程工廠類,用于創(chuàng)建線程。
RejectedExecutionHandler 工作隊(duì)列飽和策略,比如丟棄、拋出異常等。
線程池創(chuàng)建完成后,可通過execute方法提交任務(wù),線程池根據(jù)當(dāng)前運(yùn)行狀態(tài)和特定參數(shù)對(duì)任務(wù)進(jìn)處理,整體模型如下圖:
在 ThreadPoolDemo 的內(nèi)部,維護(hù)了一個(gè)阻塞隊(duì)列 workQueue 和一組工作線程,工作線程的個(gè)數(shù)由構(gòu)造函數(shù)中的 poolSize 來指定。用戶通過調(diào)用 execute() 方法來提交 Runnable 任務(wù),execute() 方法的內(nèi)部實(shí)現(xiàn)僅僅是將任務(wù)加入到 workQueue 中。ThreadPoolDemo 內(nèi)部維護(hù)的工作線程會(huì)消費(fèi) workQueue 中的任務(wù)并執(zhí)行任務(wù),相關(guān)的代碼就是代碼中的 while 循環(huán)。
以上就是對(duì)線程池的工作原理的探究,就整個(gè)線程池工作原理而言,其中最重要的還是線程池的飽和策略,用戶通過實(shí)現(xiàn)RejectedExecutionHandler接口自定義飽和策略,并通過ThreadPoolExecutor多參的構(gòu)造函數(shù)傳入。也許你看完了本文,對(duì)線程池的工作原理理解的還不夠透徹,那么請(qǐng)觀看本站的多線程教程吧,讓你全面掌握多線程相關(guān)知識(shí)!
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
有基礎(chǔ) 直達(dá)就業(yè)
業(yè)余時(shí)間 高薪轉(zhuǎn)行
工作1~3年,加薪神器
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問老師會(huì)電話與您溝通安排學(xué)習(xí)
初級(jí) 202925
初級(jí) 203221
初級(jí) 202629
初級(jí) 203743