Java中的ThreadPoolExecutor線程池原理細(xì)節(jié)解析
一、什么是ThreadPoolExecutor
ThreadPoolExecutor是一個線程池,最多可使用7個參數(shù)來控制線程池的生成。 使用線程池可以避免創(chuàng)建和銷毀線程的資源損耗,提高響應(yīng)速度,并且可以管理線程池中線程的數(shù)量和狀態(tài)等等。 阿里巴巴手冊中也推薦使用該線程池,因?yàn)镋xecutors創(chuàng)建緩存線程池時,最大線程數(shù)是Integer.MAX_VALUE,可能導(dǎo)致堆棧溢出。而且使用ThreadPoolExecutor創(chuàng)建線程池可以讓開發(fā)者更好理解線程池原理。
二、使用線程池的優(yōu)點(diǎn)
1.減少系統(tǒng)資源消耗
無須重復(fù)創(chuàng)建和銷毀線程,減少了線程創(chuàng)建和銷毀造成的資源消耗。
2.提高響應(yīng)速度
創(chuàng)建好的線程會駐留在線程池中,無需創(chuàng)建新線程執(zhí)行任務(wù),因而提高了響應(yīng)速度。
3.提高了線程的可管理性。
線程池可以控制線程的數(shù)量,可以選擇拒絕策略,可以監(jiān)控和管理線程的狀態(tài),控制并發(fā)量等等。 這些都是自己創(chuàng)建線程難以做到的。
三、線程池原理
3.1 線程池的7個參數(shù)
1)corePoolSize 核心線程數(shù)
線程池常駐線程數(shù)量
2)maximumPoolSize 最大線程數(shù)
最大可存在的線程數(shù)量
3)keepAliveTime 非核心線程的存活時間
非核心線程空閑時,可以停留的時間
4)unit 存活時間的單位
非核心線程空閑時,可以停留的時間的單位
5)workQueue 阻塞隊列
線程都在使用中時,可以將任務(wù)保存在阻塞隊列中,可以設(shè)置隊列的長度。
6)threadFactory 線程創(chuàng)建工廠
可以選擇創(chuàng)建線程的工廠
7)handler 拒絕策略
當(dāng)線程池?zé)o法存放更多任務(wù)時,處理這些過多的任務(wù)的策略
3.2 線程池執(zhí)行任務(wù)的流程
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//判斷工作線程數(shù)是否小于核心線程數(shù)
if (workerCountOf(c) < corePoolSize) {
//是,創(chuàng)建一個新線程
if (addWorker(command, true))
return;
c = ctl.get();
}
//否,將任務(wù)嘗試添加到阻塞隊列中,如果隊列滿了則會添加失敗。
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
//判斷線程池狀態(tài)是否在運(yùn)行中,不在運(yùn)行中時,刪除該任務(wù)
if (! isRunning(recheck) && remove(command))
//不在運(yùn)行中時,執(zhí)行拒絕策略
reject(command);
//判斷工作線程數(shù)是否為0
else if (workerCountOf(recheck) == 0)
//為0的場合,嘗試創(chuàng)建新線程
addWorker(null, false);
}
//添加失敗的場合,嘗試創(chuàng)建一個新線程
else if (!addWorker(command, false))
//如果添加失敗,執(zhí)行拒絕策略
reject(command);
}- 當(dāng)執(zhí)行一個任務(wù)時,首先會判斷工作線程數(shù)是否小于核心線程數(shù)。
- 如果小于核心線程數(shù),則創(chuàng)建一個新線程來執(zhí)行該任務(wù)。執(zhí)行完畢。
- 如果大于核心線程數(shù),則嘗試將任務(wù)放入阻塞隊列中。
- 如果成功放入阻塞隊列,待有空閑的線程時,空閑線程會從阻塞隊列中獲取任務(wù)并執(zhí)行。執(zhí)行完畢。
- 如果放入失敗,表示阻塞隊列已滿,此時會嘗試創(chuàng)建一個新線程來執(zhí)行該任務(wù)。
- 如果當(dāng)前線程數(shù)小于最大線程數(shù),則會創(chuàng)建新線程來執(zhí)行該任務(wù)。執(zhí)行完畢。
- 如果工作線程數(shù)等于最大線程數(shù),則不會創(chuàng)建新線程,嘗試創(chuàng)建失敗。此時會執(zhí)行拒絕策略。執(zhí)行完畢。
四、Executors提供的常用線程池
4.1 Executors.newFixedThreadPool
一個固定數(shù)量的線程池,可以通過傳入的參數(shù)int nThreads來控制線程池的線程數(shù)量。(核心線程數(shù)和最大線程數(shù)相同)
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}4.2 Executors.newSingleThreadExecutor
一個線程數(shù)只有1的線程池??梢员WC任務(wù)的順序執(zhí)行。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}4.3 Executors.newCachedThreadPool
緩存線程池,新創(chuàng)建的線程會在該線程池中緩存60秒。可以提高短期異步任務(wù)的性能。 注意,最大線程數(shù)是Integer.MAX_VALUE,高并發(fā)的場合下,可能會創(chuàng)建大量線程。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}4.4 Executors.newScheduledThreadPool
定時任務(wù)線程池,使用該線程池可以定時執(zhí)行任務(wù)。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}到此這篇關(guān)于Java中的ThreadPoolExecutor線程池原理細(xì)節(jié)解析的文章就介紹到這了,更多相關(guān)ThreadPoolExecutor線程池原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MyBatis-Flex實(shí)現(xiàn)多表聯(lián)查(自動映射)
我們可以輕松的使用 Mybaits-Flex 鏈接任何數(shù)據(jù)庫,本文主要介紹了MyBatis-Flex實(shí)現(xiàn)多表聯(lián)查(自動映射),具有一定的參考價值,感興趣的可以了解一下2024-06-06
使用lombok的@Data會導(dǎo)致棧溢出StackOverflowError問題
這篇文章主要介紹了使用lombok的@Data會導(dǎo)致棧溢出StackOverflowError問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-11-11
Java實(shí)現(xiàn)自定義自旋鎖代碼實(shí)例
這篇文章主要介紹了Java實(shí)現(xiàn)自定義自旋鎖代碼實(shí)例,Java自旋鎖是一種線程同步機(jī)制,它允許線程在獲取鎖時不立即阻塞,而是通過循環(huán)不斷嘗試獲取鎖,直到成功獲取為止,自旋鎖適用于鎖競爭激烈但持有鎖的時間很短的情況,需要的朋友可以參考下2023-10-10
Java中數(shù)據(jù)轉(zhuǎn)換及字符串的“+”操作方法
本文主要介紹了Java中的數(shù)據(jù)類型轉(zhuǎn)換,包括隱式轉(zhuǎn)換和強(qiáng)制轉(zhuǎn)換,隱式轉(zhuǎn)換通常用于將范圍較小的數(shù)據(jù)類型轉(zhuǎn)換為范圍較大的數(shù)據(jù)類型,而強(qiáng)制轉(zhuǎn)換則是將范圍較大的數(shù)據(jù)類型轉(zhuǎn)換為范圍較小的數(shù)據(jù)類型,本文介紹Java中數(shù)據(jù)轉(zhuǎn)換以及字符串的“+”操作,感興趣的朋友一起看看吧2024-10-10

