線程池主要解決兩個問題:當執行多個異步任務時,能夠實驗線程池來提升性能,由於使用線程池能夠減小了每一個任務的調用開銷,而且提供了限制和管理資源的方式,例如線程資源。當線程池執行一個任務集合時,它也會持有一些基本的統計數據,例如完成任務的數量。爲了可以在普遍的環境中可用,這個類提供了不少可調整的參數和一些可擴展的鉤子。然而程序員都更加喜歡使用一些工廠方法:Executors#newCachedThreadPool(無界線程池而且線程可自動回收)、Executors#newFixedThreadPool(固定大小的線程池)、Executors#newSingleThreadExecutor(單個後臺線程),這些工廠已經預配置的最經常使用的場景,你也能夠手動的按照以下的指南配置和調整這個類:程序員
ThreadPoolExecutor能夠根據核心線程數和最大線程數自動調整池的大小。
當調用方法execute(Runable)
提交一個新的任務時:安全
建立一個新的線程處理請求,即便其餘的工做線程處於空閒狀態。服務器
只有隊列滿時纔會從新建立一個新的線程。併發
經過設置corePoolSize=maximumPoolSize,你能夠建立一個大小固定的線程池。異步
經過設置maximumPoolSize爲一個無窮大數值(例如Integer.MAX_VALUE),那麼說明你配置的線程池能夠容納任意數量的併發任務。性能
通常狀況下,corePoolSize和maximumPoolSize都會在建立的時候指定的,可是大家也能夠經過調用setCorePoolSize()
和setMaximumPoolSize()
來動態的調整這兩個值。操作系統
默認狀況下,核心線程只有當任務到達時纔會進行建立和開啓,可是能夠重寫方法`prestartCoreThread`或者`prestartAllCoreThreads`改變這個行爲。若是你構建的線程池帶有一個非空的隊列,你可能須要提早開啓一些線程。
新的線程是經過使用ThreadFactory
來建立的,若是沒有指定的話,就會使用默認的Executors#defaultThreadFactory
,這個默認的工廠建立出的線程都具備相同的ThreadGroup
和相同的優先級而且都不是後臺線程。經過實現一個不一樣的線程工廠,你能夠修改線程的名字、線程組、優先級、後臺狀態等等。若是ThreadFactory在從newThread中返回null時未能建立線程,則執行程序將繼續,但可能沒法執行任何任務。線程應該具備修改線程的權限。若是工做線程或者其餘線程使用線程池是不具備這個權限,服務能夠會被降級:配置改變可能沒法及時生效,and a shutdown pool may remain in a* state in which termination is possible but not completed。.net
若是線程池有超過corePoolSize數的線程數,若是這些過量的線程空閒時間超過`keepAliveTime`將會被終止。當線程池沒有被使用充分時,這種機制能夠下降資源的消耗。當線程池以後又變得活躍起來,新的線程又會被建立。這個參數能夠被動態的改變,使用`setKeepAliveTime(long,TimeUnit)`。經過使用`Integer.MAX_VALUE`能夠有效的禁用此功能。默認狀況下,只有當前的線程數大於corePoolSize,這個策略纔會生效。可是方法`allowCoreThreadTimeOut(boolean)`也可以將核心線程使用這種策略,只要`keepAliveTime`非0便可。
任何`BlockingQueue`均可以用來傳輸和保存提交的任務,此隊列的使用和線程池大小有以下的交互:
Executor會建立一個新的線程而不是添加到隊列中。線程
Executor會將任務添加到隊列中而不是建立一個新的線程。調試
隊列有三種常見的策略:
LinkedBlockingQueue
,當全部的核心線程處於繁忙時,全部新的任務都會被添加到隊列中。所以若是運行線程數不超過corePoolSize,將會建立一個新的線程(maximumPoolSize這個值將不會再起做用),當每一個任務徹底獨立於其餘任務時,這多是合適的,所以任務不能影響彼此的執行。在一個網頁服務器。雖然這種排隊方式能夠有效地消除瞬時突發請求,可是當命令以比它們能夠被處理的速度更快地平均到達時,可能會致使無限制的工做隊列增加。當Executor已經被關閉時,再調用`execute(Runable)`方法添加一個任務時將會被拒絕,當Executor使用有界隊列時,隊列和最大線程數都已經飽和,將會調RejectedExecutionHandler#rejectedExecution(Runnable, ThreadPoolExecutor)方法。提供4種預約義的處理器:
ThreadPoolExecutor.AbortPolicy:該處理器拋出一個運行時異常RejectedExecutionException。
ThreadPoolExecutor.CallerRunsPolicy:使用調用者本身的線程運行任務。 提供了一個簡單的反饋控制機制,能夠減慢提交新任務的速度。
ThreadPoolExecutor.DiscardPolicy:丟棄任務。
ThreadPoolExecutor.DiscardOldestPolicy:若是executor尚未被關閉,隊列頭部的任務將會被丟棄,而且從新執行(可能再一次失敗,可是會重複執行)
你能夠定義並使用其餘的實現自RejectedExecutionHandler的類。要作到這一點須要特別注意,特別是在策略僅在特定能力或排隊政策下工做的狀況下。
這個類提供一寫被protected修飾的方法:
beforeExecute(Thread, Runnable)
,afterExecute(Runnable, Throwable)
這些方法會在每一個任務執行以前和執行以後被調用,這些能夠用來操做執行環境;例如:從新初始化ThreadLocals,收集統計數據,或者添加log。另外,terminated
也能夠被重寫當執行程序徹底終止後須要執行的特殊處理。
若是鉤子或者callback方法拋出異常,內部工做線程可能會失敗並忽然終止。
方法`getQueue()`運行訪問工做隊列以此來進行監控和調試。強烈建議不要將這種方法用於任何其餘目的。當大量的排隊的任務被取消時,兩個提供的方法`remove()`和`purge()`可用來幫助存儲回收。
當線程池在程序中不在被引用而且再也不持有線程,將會自動關閉。若是你但願確保即便用戶忘記調用`shutdown()`也能夠回收未引用的線程池,那麼必須設置適當的保持活動的時間,使用0核心線程的下限來安排未使用的線程最終死亡或設置`allowCoreThreadTimeOut(boolean)`