在操做系統中,線程是一個很是重要的資源,頻繁建立和銷燬大量線程會大大下降系統性能。Java線程池原理相似於數據庫鏈接池,目的就是幫助咱們實現線程複用,減小頻繁建立和銷燬線程
java
ThreadPoolExecutor是線程池的核心類。首先看一下如何建立一個ThreadPoolExecutor。下面是ThreadPoolExecutor經常使用的一個構造方法:數據庫
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.acc = System.getSecurityManager() == null ? null : AccessController.getContext(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }
使用案例併發
/** * 阻塞的線程池 */ private ThreadPoolExecutor executor = new ThreadPoolExecutor( 0, // corePoolSize:線程池維護線程的最少數量 4, // maximumPoolSize:線程池維護線程的最大數量 10000, // keepAliveTime:線程池維護線程所容許的空閒時間 TimeUnit.MILLISECONDS, // unite:線程池維護線程所容許的空閒時間的單位 new LinkedBlockingQueue<>(200), // workQueue:線程池所使用的緩衝隊列 new CallerBlockedPolicy() // handler:線程池對拒絕任務的處理策略,自定義拓展 );
execute()
方法提交時,會執行如下判斷:
corePoolSize
,則建立新線程來處理任務,即便線程池中的其餘線程是空閒的;corePoolSize
且小於 maximumPoolSize
,則只有當workQueue
滿時才建立新的線程去處理任務;corePoolSize
和 maximumPoolSize
相同,則建立的線程池的大小是固定的,這時若是有新任務提交,若workQueue
未滿,則將請求放入workQueue
中,等待有空閒的線程去從workQueue
中取任務並處理;corePoolSize
的時候,把該任務封裝成一個Worker
對象放入等待隊列;SynchronousQueue
,但如今尚未研究過該隊列,這裏暫時還無法介紹;LinkedBlockingQueue
。若是使用這種方式,那麼線程池中可以建立的最大線程數就是corePoolSize
,而maximumPoolSize
就不會起做用了(後面也會說到)。當線程池中全部的核心線程都是RUNNING狀態時,這時一個新的任務提交就會放入等待隊列中。ArrayBlockingQueue
。使用該方式能夠將線程池的最大線程數量限制爲maximumPoolSize
,這樣可以下降資源的消耗,但同時這種方式也使得線程池對線程的調度變得更困難,由於線程池和隊列的容量都是有限的值,因此要想使線程池處理任務的吞吐率達到一個相對合理的範圍,又想使線程調度相對簡單,而且還要儘量的下降線程池對資源的消耗,就須要合理的設置這兩個數量。
setMaximumPoolSize()
方法來從新設定線程池的容量。corePoolSize
的時候,若是這時沒有新的任務提交,核心線程外的線程不會當即銷燬,而是會等待,直到等待的時間超過了keepAliveTime
;Executors.defaultThreadFactory()
來建立線程。使用默認的- - - - ThreadFactory來建立線程時,會使新建立的線程具備相同的NORM_PRIORITY優先級而且是非守護線程,同時也設置了線程的名稱。RejectedExecutionHandler
類型的變量,表示線程池的飽和策略。若是阻塞隊列滿了而且沒有空閒的線程,這時若是繼續提交任務,就須要採起一種策略處理該任務。線程池提供了4種策略:
經過線程池提供的參數進行監控。線程池裏有一些屬性在監控線程池的時候可使用性能
總結一下線程池添加任務的整個流程:this