線程池,使用ThreadPoolExecutor代替Executors創(chuàng)建方式

image.png

合理使用線程池的好處:

  • 降低資源消耗。通過(guò)重復(fù)利用已創(chuàng)建的線程降低線程創(chuàng)建和銷毀造成的消耗。
  • 提高響應(yīng)速度。當(dāng)任務(wù)到達(dá)時(shí),任務(wù)可以不需要的等到線程創(chuàng)建就能立即執(zhí)行。
  • 提高線程的可管理性。線程是稀缺資源,如果無(wú)限制的創(chuàng)建,不僅會(huì)消耗系統(tǒng)資源,還會(huì)降低系統(tǒng)的穩(wěn)定性,使用線程池可以進(jìn)行統(tǒng)一的分配,調(diào)優(yōu)和監(jiān)控。但是要做到合理的利用線程池,必須對(duì)其原理了如指掌

Executor架構(gòu)

image.png

在HotSpot虛擬機(jī)中,Java中的線程將會(huì)被一一映射為操作系統(tǒng)的線程 在Java虛擬機(jī)層面,用戶將多個(gè)任務(wù)提交給Executor框架,Executor負(fù)責(zé)分配線程執(zhí)行它們; 在操作系統(tǒng)層面,操作系統(tǒng)再將這些線程分配給處理器執(zhí)行


image.png

Executor框架中的所有類可以分成三類:
1.任務(wù) 任務(wù)有兩種類型:Runnable和Callable。
2.任務(wù)執(zhí)行器 Executor框架最核心的接口是Executor,它表示任務(wù)的執(zhí)行器。
Executor的子接口為ExecutorService。
ExecutorService有兩大實(shí)現(xiàn)類:ThreadPoolExecutor和ScheduledThreadPoolExecutor。
3.執(zhí)行結(jié)果
Future接口表示異步的執(zhí)行結(jié)果,它的實(shí)現(xiàn)類為FutureTask。

ThreadPoolExecutor類

image.png

Executor接口

Executor接口只有一個(gè)execute方法,用來(lái)替代通常創(chuàng)建或啟動(dòng)線程的方法。

ExecutorService接口

ExecutorService接口繼承自Executor接口,提供了管理終止的方法,以及可為跟蹤一個(gè)或多個(gè)異步任務(wù)執(zhí)行狀況而生成 Future 的方法。增加了shutDown(),shutDownNow(),invokeAll(),invokeAny()和submit()等方法。如果需要支持即時(shí)關(guān)閉,也就是shutDownNow()方法,則任務(wù)需要正確處理中斷。

AbstractExecutorService抽象類

提供ExecutorService接口的默認(rèn)實(shí)現(xiàn)方法。

創(chuàng)建線程池的方法

ExecutorService threadPool = new ThreadPoolExecutor(1, 5, 30, TimeUnit.MILLISECONDS,new LinkedBlockingDeque<Runnable>(1024), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

其中線程工廠可以使用guava包中的方法創(chuàng)建:

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();

參數(shù)說(shuō)明:

  • corePoolSize
    核心線程數(shù),默認(rèn)情況下核心線程會(huì)一直存活,即使處于閑置狀態(tài)也不會(huì)受存keepAliveTime限制。除非將allowCoreThreadTimeOut設(shè)置為true。
  • maximumPoolSize
    線程池所能容納的最大線程數(shù)。超過(guò)這個(gè)數(shù)的線程將被阻塞。當(dāng)任務(wù)隊(duì)列為沒(méi)有設(shè)置大小的LinkedBlockingDeque時(shí),這個(gè)值無(wú)效。
  • keepAliveTime
    非核心線程的閑置超時(shí)時(shí)間,超過(guò)這個(gè)時(shí)間就會(huì)被回收。
  • workQueue
    線程池中的任務(wù)隊(duì)列。常用的有三種隊(duì)列,SynchronousQueue,LinkedBlockingDeque,ArrayBlockingQueue。
  • threadFactory
    線程工廠,提供創(chuàng)建新線程的功能。
  • RejectedExecutionHandler
    當(dāng)線程池中的資源已經(jīng)全部使用,添加新線程被拒絕時(shí),會(huì)調(diào)用RejectedExecutionHandler的rejectedExecution方法。

線程池規(guī)則:
1.如果線程數(shù)量<=核心線程數(shù)量,那么直接啟動(dòng)一個(gè)核心線程來(lái)執(zhí)行任務(wù),不會(huì)放入隊(duì)列中。
2.如果線程數(shù)量>核心線程數(shù),但<=最大線程數(shù),并且任務(wù)隊(duì)列是LinkedBlockingDeque的時(shí)候,超過(guò)核心線程數(shù)量的任務(wù)會(huì)放在任務(wù)隊(duì)列中排隊(duì)。
3.如果線程數(shù)量>核心線程數(shù),但<=最大線程數(shù),并且任務(wù)隊(duì)列是SynchronousQueue的時(shí)候,線程池會(huì)創(chuàng)建新線程執(zhí)行任務(wù),這些任務(wù)也不會(huì)被放在任務(wù)隊(duì)列中。這些線程屬于非核心線程,在任務(wù)完成后,閑置時(shí)間達(dá)到了超時(shí)時(shí)間就會(huì)被清除。
4.如果線程數(shù)量>核心線程數(shù),并且>最大線程數(shù),當(dāng)任務(wù)隊(duì)列是LinkedBlockingDeque,會(huì)將超過(guò)核心線程的任務(wù)放在任務(wù)隊(duì)列中排隊(duì)。也就是當(dāng)任務(wù)隊(duì)列是LinkedBlockingDeque并且沒(méi)有大小限制時(shí),線程池的最大線程數(shù)設(shè)置是無(wú)效的,他的線程數(shù)最多不會(huì)超過(guò)核心線程數(shù)。
5.如果線程數(shù)量>核心線程數(shù),并且>最大線程數(shù),當(dāng)任務(wù)隊(duì)列是SynchronousQueue的時(shí)候,會(huì)因?yàn)榫€程池拒絕添加任務(wù)而拋出異常。


image.png

使coreThread失效

之前設(shè)置的keepAliveTime參數(shù)只能使超過(guò)此閾值的非核心線程失效,使用allowCoreThreadTimeOut(boolean value)方法將allowCoreThreadTimeOut設(shè)置為true則可以將該策略應(yīng)用于核心線程。

http://www.ideabuffer.cn/2017/04/04/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3Java%E7%BA%BF%E7%A8%8B%E6%B1%A0%EF%BC%9AThreadPoolExecutor/
https://blog.csdn.net/z_s_z2016/article/details/81674893

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容