java自定义线程_Java自定义线程池详解
自定義線程池的核心:ThreadPoolExecutor
為了更好的控制多線程,JDK提供了一套線程框架Executor,幫助開發人員有效的進行線程控制,其中在java.util.concurrent包下,是JDK并發包的核心,比如我們熟知的Executors。Executors扮演著線程工廠的角色,我們通過它可以創建特定功能的線程池,而這些線程池背后的就是:ThreadPoolExecutor。那么下面我們來具體分析下它。
構造ThreadPoolExecutor
public?ThreadPoolExecutor(int?corePoolSize,
int?maximumPoolSize,
long?keepAliveTime,
TimeUnit?unit,
BlockingQueue?workQueue,
ThreadFactory?threadFactory,
RejectedExecutionHandler?handler)?{
if?(corePoolSize?
maximumPoolSize?<=?0?||
maximumPoolSize?
keepAliveTime?
throw?new?IllegalArgumentException();
if?(workQueue?==?null?||?threadFactory?==?null?||?handler?==?null)
throw?new?NullPointerException();
this.corePoolSize?=?corePoolSize;
this.maximumPoolSize?=?maximumPoolSize;
this.workQueue?=?workQueue;
this.keepAliveTime?=?unit.toNanos(keepAliveTime);
this.threadFactory?=?threadFactory;
this.handler?=?handler;
}
corePoolSize:核心線程數
maximumPoolSize:最大線程數
keepAliveTime + unit:線程回收時間
workQueue:任務較多時暫存到隊列
threadFactory:執行程序創建新線程時使用的工廠
handler:超出線程池容量以及隊列長度后拒絕任務的策略
有界隊列 or ×××隊列
我們知道對于BlockingQueue而言,有典型的有界隊列ArrayBlockingQueue以及LinkedBlockingQueue這種×××隊列,那么對于線程池而言,workQueue采用有界隊列、×××隊列會產生什么影響呢?如果采用×××隊列,那么會存在拒絕策略嗎?顯然不會,因為容量是無限的,比如沒有預定義容量的LinkedBlockingQueue。比如,在某個時段突發很多請求,那么采用×××隊列就保證了增長的可能性,而不是拒絕。如果采用有界隊列,相比×××隊列而言,有助于防止資源耗盡,在實際中我們經常在拒絕策略中記錄log,然后通過定時任務的方式進行處理。
接著上面的分析思路,想一想采用有界隊列、×××隊列中線程池的大小,這里涉及到一個問題,那就是任務增長時,是先增長至maximumPoolSize,還是先暫存到隊列中的問題?
corePoolSize and maximumPoolSize
一個是核心線程數,一個是最大線程數,怎么理解呢?在線程池初始化階段,是否已經初始化好corePoolSize個線程呢?大量任務來了后,線程池中的線程怎么變化?任務完成處理后,線程池又是如何回收的,回收到什么程度?
下面先來看一個線程池處理流程圖:
簡單一句話:提交任務,線程池中的線程數可以增長至corePoolSize,之后繼續提交任務將暫存至隊列中,如果隊列滿,則看是否能繼續增長線程數至maximumPoolSize,超出后將進行拒絕策略處理。顯然,如果采用×××隊列,那么maximumPoolSize將失效,線程池中的線程最多就是corePoolSize個線程工作。
從這里我們也可以看出,在需要判斷是否corePoolSize是否已經達到,需要鎖的介入,因此我們應盡量讓線程啟動后線程池的大小就處于>=corePoolSize個數,提前預熱。
keepAliveTime + unit
這里涉及到線程池回收線程。簡單來說,就是采用有界隊列,導致corePoolSize滿,隊列滿,不得已線程池的線程增長至maximumPoolSize,那么任務處理完畢后,線程池中多出corePoolSize的部分理應回收,那么等待多長時間,多長時間沒有任務后在進行回收的問題就是由上面的參數決定。
Executors創建線程池實例分析
固定線程池
特點:
×××隊列,導致keepAliveTime/unit/maximumPoolSize失效,不存在拒絕;
隨著任務的增長,線程數將固定在corePoolSize。
緩存線程池
特點:
一個比較特殊的隊列:SynchronousQueue,沒有容量可言,提交任務就意味著一直阻塞等待任務的線程立刻得到任務進行執行。說白了,就是不要暫存到隊列中,任務直接提交給線程進行執行。由于任務無法暫存,因此緩存線程池會根據任務的實際情況,進行線程池的增長,直至maximumPoolSize(Integer.MAX_VALUE)。
注意到keepAliveTime被設置成了60S,意思就是說如果任務來了很多,緩存線程池創建了不少線程來對付它們,任務處理的差不多了,那么等待60S后,還沒有任務需要處理,那么進行線程回收處理。
單線程池
特點:
×××隊列+核心、最大線程數都是1。
打個簡單比喻,任務來了,不管多少,那么有序的放著,工人只有一個,那就按照順序處理任務就是了。就是一個單線程順序處理任務的情況。
定時線程池
特點:
利用延時隊列DelayedQueue(×××隊列),完成線程池實現定時以及周期性執行任務的需要。
拒絕策略
JDK已經提供了幾種拒絕策略,如下所示:
我們需要自定義決絕策略時,很簡單,直接實現RejectedExecutionHandler的rejectedExecution方法即可。
總結
以上是生活随笔為你收集整理的java自定义线程_Java自定义线程池详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对标DLSS之后 AMD显卡又瞄准了NV
- 下一篇: 索尼问卷调研Xperia手机系统:或将全