重用線程池中的線程,避免因為線程的建立和銷毀帶來的性能消耗
能有效的控制線程的最大并發數,避免大量的線程之間因搶占系統資源而導緻的阻塞現象
能夠對線程進行簡單的管理,并提供定時執行以及指定間隔循環執行等功能
Android中,用ThreadPoolExecutor來實作線程池的配置。
<a href="https://link.jianshu.com/?t=http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/java/util/concurrent/ThreadPoolExecutor.html" target="_blank">ThreadPoolExecutor文檔中文版</a>
<a href="https://link.jianshu.com/?t=https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html" target="_blank">ThreadPoolExecutor文檔英文版</a>

QQ截圖20160711141312.png
ThreadPoolExecutor的構造方法有四個,其實作如下:
```
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
corePoolSize
程池中的核心線程數,也就是是線程池中的最小線程數;
核心線程在allowCoreThreadTimeout被設定為true時會逾時退出,預設情況下不會退出;
maximumPoolSize
最大線程池大小,當活動線程數達到這個值,後續任務會被阻塞
keepAliveTime
線程池中超過corePoolSize數目的非核心線程最大存活時間;閑置時的逾時時長,超過這個值後,閑置線程就會被回收
unit
workQueue
執行前用于保持任務的隊列,也就是線程池的緩存隊列。此隊列僅保持由 execute 方法送出的 Runnable 任務
<a href="https://link.jianshu.com/?t=http://dongxuan.iteye.com/blog/901689" target="_blank">關于三種送出政策這篇文章不錯</a>
threadFactory
線程工廠,為線程池提供建立新線程的功能,它是一個接口,隻有一個方法:<code>Thread newThread(Runnable r)</code>
RejectedExecutionHandler
線程池對拒絕任務的處理政策。一般是隊列已滿或者無法成功執行任務,這時ThreadPoolExecutor會調用handler的rejectedExecution方法來通知調用者
ThreadPoolExecutor預設有四個拒絕政策:
也可以自己繼承RejectedExecutionHandler來寫拒絕政策.
一個任務通過 execute(Runnable)方法被添加到線程池,任務就是一個 Runnable類型的對象,任務的執行方法就是Runnable類型對象的run()方法。
當線程池小于corePoolSize時,新送出任務将建立一個新線程執行任務,即使此時線程池中存在空閑線程
當線程池達到corePoolSize時,新送出任務将被放入workQueue中,等待線程池中任務排程執行
當送出任務數超過【maximumPoolSize+阻塞隊列大小】時,新送出任務由RejectedExecutionHandler處理 (關于這裡,網上90%以上的人說當任務數>=maximumPoolSize時就會被拒絕,我不知道依據在哪裡,也不知道代碼驗證過沒,經過我的驗證這種說法是不成立的,具體的看下邊日志分析)
當線程池中超過corePoolSize線程,空閑時間達到keepAliveTime時,關閉空閑線程
當設定allowCoreThreadTimeOut(true)時,線程池中corePoolSize線程空閑時間達到keepAliveTime也将關閉
定制自己的線程池:
日志資訊:
QQ截圖20160712161004.png
下面就來對日志資訊進行分析:
上邊粉色部分(1~6行),可以看到poolsize逐漸累加,一直加到最大線程數後不再增加,這呼應了上述“執行過程1”
接下來綠色部分()7行,驗證了上邊我們說的“執行過程3”,緩存隊列數為2,最大線程數為3,共有6條任務,是以會有【 6-(2+3)】條任務被拒絕,這裡拒絕政策我們用的是<code>ThreadPoolExecutor.AbortPolicy()</code>也就是直接抛出異常,也就是我們日志的第7行
然後8~22行是任務的執行過程,
其中藍色部分(8~16)行,我們可以看到有3條任務在同時執行,也就是最大線程數
接下來的綠色(17~22行),在三條任務執行完成後,剩餘的排隊任務才開始執行
最後,23行,20s後,線程都處于空閑狀态,是以非核心線程會被回收,但是因為代碼中我們設定了<code>executorPool.allowCoreThreadTimeOut(true)</code>,是以這時處于空閑狀态的核心線程也會被回收,這時池中的線程數為0
關于線程池的一些建議
最大線程數一般設為2N+1最好,N是CPU核數
其實,本應該先說官方定義的這四種線程池,然後再說自定義線程池,但是考慮到裡邊的一些配置參數,是以本帖先利用自定義線程池把各個配置參數理一下,然後再講官方定義的四種線程池,這樣也便于了解官方定義的這四種線程池
這四種線程池都是通過Executors的工廠方法來實作
他是一種數量固定的線程池,且任務隊列也沒有大小限制;
它隻有核心線程,且這裡的核心線程也沒有逾時限制,是以即使線程處于空閑狀态也不會被回收,除非線程池關閉;
當所有的任務處于活動狀态,新任務都處于等待狀态,知道所有線程空閑出來;
因為它不會被回收,是以它能更快的響應;
源碼:
實作:
無界線程池,可以進行自動線程回收
他是一種線程數量不固定的線程池;
它隻有非核心線程,且最大線程數為Integer.MAX_VALUE,也就是說線程數可以任意大;
當池中的線程都處于活動狀态時,會建立新的線程來處理任務,否則會利用空閑線程來處理任務;是以,任何添加進來的任務都會被立即執行;
池中的空閑線程都有逾時限制,為60s,超過這個限制就會被回收,當池中的所有線程都處于閑置狀态時,都會因逾時而被回收,這個時候,她幾乎不占用任何系統資源;
适合做大量的耗時較少的任務;
隻有一個核心線程,所有任務都在同一線程中按序執行,這樣也就不需要處理線程同步的問題;
它的核心線程數量是固定的,而非核心線程是沒有限制的,且非核心線程空閑時會被回收;
适合執行定時任務和具有固定周期的任務
由于本人技術有限,避免不了出現一些錯誤或者了解有偏差描述不清楚的地方,請大家諒解并提醒我:)
<a href="https://www.jianshu.com/p/c4b0b14a234d" target="_blank">上一篇:AsyncTask</a>
<a href="https://www.jianshu.com/p/2d8d7ed8c92a" target="_blank">再來一篇:java中的thread</a>
轉載請注明出處!
本文轉自 一點點征服 部落格園部落格,原文連結:http://www.cnblogs.com/ldq2016/p/8056744.html,如需轉載請自行聯系原作者