講解線程池原理之前弃舒,首先了解一下什么是線程池:
????????線程池是指在初始化一個多線程應(yīng)用程序過程中創(chuàng)建一個線程集合援奢,然后在需要執(zhí)行新的任務(wù)時重用這些線程而不是新建一個線程。線程池中的每個線程都有被分配一個任務(wù),一旦任務(wù)已經(jīng)完成了灶芝,線程回到線程池中并等待下一次分配任務(wù)宽堆。
至于為什么要使用線程池腌紧?
????????對于操作系統(tǒng)來說,頻繁的創(chuàng)建銷毀線程會消耗大量的資源畜隶。所以可以創(chuàng)建線程池來統(tǒng)一管理這些運(yùn)行的線程壁肋。線程用于在需要執(zhí)行大量異步任務(wù)的情況下,使用線程池減少了每個任務(wù)運(yùn)行的負(fù)載代箭。
了解完線程池后墩划,接下來了解它是如何使用的:
????????JDK1.5提供了Executor框架,開發(fā)者可以使用線程池工廠類Executors根據(jù)不同的需求創(chuàng)建各種不同形式的線程池嗡综。常用的有以下幾種線程池:
? ? ? ? 1乙帮、newCachedThreadPool:
? ? ? ? 創(chuàng)建一個阻塞隊(duì)列為SynchronousQueue的線程池。當(dāng)調(diào)用execute方法時极景,將重用空閑的工作線程察净。如果沒有工作線程可利用,則將創(chuàng)建新的工作線程并添加到線程池盼樟∏饪ǎ空閑線程超過60s將會被回收。
????????2晨缴、newFixedThreadPool:
? ??????創(chuàng)建一個固定數(shù)量的工作線程的線程池译秦。如果所有的工作線程在執(zhí)行任務(wù),新提交的任務(wù)將會在任務(wù)隊(duì)列中等待击碗,直到有工作線程可利用筑悴。一旦線程空閑下來就會被回收。
????????3稍途、newSingleThreadExecutor:
????????創(chuàng)建只有一個工作線程的executor阁吝。(工作線程在線程池關(guān)閉之前,如果執(zhí)行任務(wù)失敗械拍,則創(chuàng)建一個新的工作線程來替代舊的工作線程)突勇。
其實(shí)大多數(shù)線程池的本質(zhì)都是初始化一個ThreadPoolExecutor對象。
????????corePoolSize:線程池核心線程數(shù)坷虑。
????????keepAliveTime:空閑線程允許的最大空閑時間甲馋。
????????defaultThreadFactory:用于創(chuàng)建線程的工廠方法。
????????maximumPoolSize: 線程池可以容納的最大線程數(shù)猖吴。
????????workQueue:用于存放任務(wù)的阻塞隊(duì)列摔刁,提交的任務(wù)需要實(shí)現(xiàn)Runnable接口。JDK提供了如下幾種阻塞隊(duì)列:
? ? ????????1、ArrayBlockingQueue:可以阻止資源的浪費(fèi)共屈,但在不可估量負(fù)載的情況下绑谣,可能出現(xiàn)吞吐量下降的情況。
????????????2拗引、LinkedBlockingQueue:當(dāng)任務(wù)提交的速度大于線程處理任務(wù)的速度時借宵,可能出現(xiàn)任務(wù)無限制提交的情況。
????????????3矾削、SynchronousQueue:每個插入操作必須等到另一個線程調(diào)用移除操作壤玫,否則插入操作一直處于阻塞狀態(tài)。
????????????4哼凯、PriorityBlockingQueue:插入的元素必須可比較欲间。
????????defaultHandler:用于處理被拒絕的任務(wù)。當(dāng)線程數(shù)到達(dá)最大線程數(shù)并且阻塞隊(duì)列達(dá)到飽和断部,execute方法會調(diào)用RejectedExecutionHandler的rejectedExecution處理被拒絕的任務(wù)猎贴。JDK提供如下幾種拒絕策略:
????????????1、ThreadPoolExecutor.AbortPolicy:默認(rèn)情況下執(zhí)行蝴光,直接拋出RejectedExecutionException運(yùn)行時異常她渴。?
????????????2、CallerRunsPolicy:線程調(diào)用execute方法執(zhí)行任務(wù)蔑祟。這種策略提供了一個反饋機(jī)制減慢新任務(wù)的提交速度趁耗。
????????????3、DiscardPolicy:直接丟棄新提交的任務(wù) 疆虚。
????????????4苛败、DiscardOldestPolicy:如果executor沒有關(guān)閉,隊(duì)列頭的任務(wù)將會被丟棄径簿,然后executor重新嘗試執(zhí)行任務(wù)(如果失敗著拭,則重復(fù)這一過程)。
????????????5牍帚、我們也可以自己定義RejectedExecutionHandler以適應(yīng)特殊環(huán)境的需求。
然后來了解一下線程池狀態(tài)乳蛾。
????????在ThreadPoolExecutor類中有個ctl變量用于顯示線程池狀態(tài)暗赶。其中AtomicInteger是一個提供原子操作的Integer類,保證多線程情況下ctl的變化是線程安全的肃叶。ctl是個神奇的變量蹂随,它的高3位用于顯示線程池狀態(tài),低29位用于顯示線程池中的線程數(shù)因惭。
????????1岳锁、RUNNING:接受新的任務(wù),處理隊(duì)列任務(wù)蹦魔。
????????2激率、SHUTDOWN:不再接受新的任務(wù)咳燕,處理隊(duì)列任務(wù)。
????????3乒躺、STOP:不再接受新任務(wù)招盲,不處理隊(duì)列任務(wù),中斷正在執(zhí)行的任務(wù)線程嘉冒。?
????????4曹货、TIDYING:所有的任務(wù)已經(jīng)結(jié)束,任務(wù)線程為0讳推,線程轉(zhuǎn)換到TIDYING狀態(tài)顶籽。
????????5、TERMINATED:線程池已將結(jié)束银觅,即terminated()方法執(zhí)行完礼饱。
?隨著時間的推移,線程池狀態(tài)之間也是在發(fā)生著轉(zhuǎn)化设拟,以下是幾種狀態(tài)轉(zhuǎn)化的條件慨仿。
????????1、RUNNING?->?SHUTDOWN(調(diào)用shudown方法)?
????????2纳胧、RUNNING或者SHUTDOWN -> STOP(調(diào)用shutdown方法)
????????3镰吆、SHUTDOWN -> TIDYING (當(dāng)線程池和隊(duì)列都為空)
????????4、STOP -> TIDYING (當(dāng)線程池為空)
????????5跑慕、TIDYING -> TERMINATED (terminated方法執(zhí)行完)
目前先對線程池做個大致的了解万皿,對于如何調(diào)用addWorker,runWorker等方法留到下篇再解釋核行。
????????本篇文章主要是看到占小狼大神的《深入分析java線程池的實(shí)現(xiàn)原理》牢硅,然后想有樣學(xué)樣的總結(jié)一下線程池原理,同時看了一下線程池幾個核心類的源碼并且翻譯了一下注釋芝雪,有興趣的小伙伴可以去看看注釋减余。對于這篇總結(jié),如果哪里寫的不對惩系,謝謝批評指正位岔。
參考:http://www.reibang.com/p/87bff5cc8d8c