(轉載)Android開發——Android中常見的4種線程池(保證你能看懂並理解)

0.前言併發

轉載請註明出處:http://blog.csdn.net/seu_calvin/article/details/52415337性能

使用線程池能夠給咱們帶來不少好處,首先經過線程池中線程的重用,減小建立和銷燬線程的性能開銷。其次,能控制線程池中的併發數,不然會由於大量的線程爭奪CPU資源形成阻塞。最後,線程池可以對線程進行管理,好比使用ScheduledThreadPool來設置延遲N秒後執行任務,而且每隔M秒循環執行一次。spa

下面會經過介紹線程池中的真正實現者——ThreadPoolExecutor來引出Android中的4類線程池的使用以及特性分析,會加上筆者本身的理解,和自認爲比較恰當的比喻,幫助理解。.net

 

1.凡事得靠ThreadPoolExecutor(鋪墊環節,懂的直接跳過)線程

Executor做爲一個接口,它的具體實現就是ThreadPoolExecutor。code

Android中的線程池都是直接或間接經過配置ThreadPoolExecutor來實現不一樣特性的線程池。對象

先介紹ThreadPoolExecutor的一個經常使用的構造方法。blog

 1 /* 
 2 *@ ThreadPoolExecutor構造參數介紹 
 3 *@author SEU_Calvin 
 4 * @date 2016/09/03 
 5 */  
 6 public ThreadPoolExecutor(  
 7 //核心線程數,除非allowCoreThreadTimeOut被設置爲true,不然它閒着也不會死  
 8 int corePoolSize,   
 9 //最大線程數,活動線程數量超過它,後續任務就會排隊                     
10 int maximumPoolSize,   
11 //超時時長,做用於非核心線程(allowCoreThreadTimeOut被設置爲true時也會同時做用於核心線程),閒置超時便被回收             
12 long keepAliveTime,                            
13 //枚舉類型,設置keepAliveTime的單位,有TimeUnit.MILLISECONDS(ms)、TimeUnit. SECONDS(s)等  
14 TimeUnit unit,  
15 //緩衝任務隊列,線程池的execute方法會將Runnable對象存儲起來  
16 BlockingQueue<Runnable> workQueue,  
17 //線程工廠接口,只有一個new Thread(Runnable r)方法,可爲線程池建立新線程  
18 ThreadFactory threadFactory)  

ThreadPoolExecutor的各個參數所表明的特性註釋中已經寫的很清楚了,那麼ThreadPoolExecutor執行任務時的心路歷程是什麼樣的呢?(如下用currentSize表示線程池中當前線程數量)接口

(1)當currentSize<corePoolSize時,沒什麼好說的,直接啓動一個核心線程並執行任務。隊列

(2)當currentSize>=corePoolSize、而且workQueue未滿時,添加進來的任務會被安排到workQueue中等待執行。

(3)當workQueue已滿,可是currentSize<maximumPoolSize時,會當即開啓一個非核心線程來執行任務。

(4)當currentSize>=corePoolSize、workQueue已滿、而且currentSize>maximumPoolSize時,調用handler默認拋出RejectExecutionExpection異常。

 

2. Android中的四類線程池

Android中最多見的四類具備不一樣特性的線程池分別爲FixThreadPool、CachedThreadPool、ScheduleThreadPool以及SingleThreadExecutor。

 

2.1     FixThreadPool(一堆人排隊上公廁)

 1 /* 
 2 *@FixThreadPool介紹 
 3 *@author SEU_Calvin 
 4 * @date 2016/09/03 
 5 */  
 6 public static ExecutorService newFixThreadPool(int nThreads){  
 7     return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());  
 8 }  
 9 //使用  
10 Executors.newFixThreadPool(5).execute(r);  

(1)從配置參數來看,FixThreadPool只有核心線程,而且數量固定的,也不會被回收,全部線程都活動時,由於隊列沒有限制大小,新任務會等待執行。

(2)【前方高能,筆者腦洞】FixThreadPool其實就像一堆人排隊上公廁同樣,能夠無數多人排隊,可是廁所位置就那麼多,並且沒人上時,廁所也不會被拆遷,哈哈o(∩_∩)o ,很形象吧。

(3)因爲線程不會回收,FixThreadPool會更快地響應外界請求,這也很容易理解,就好像有人忽然想上廁所,公廁不是現用現建的。

 

2.2     SingleThreadPool(公廁裏只有一個坑位)

 1 /* 
 2 *@SingleThreadPool介紹 
 3 *@author SEU_Calvin 
 4 * @date 2016/09/03 
 5 */  
 6 public static ExecutorService newSingleThreadPool (int nThreads){  
 7     return new FinalizableDelegatedExecutorService ( new ThreadPoolExecutor (1, 1, 0, TimeUnit. MILLISECONDS, new LinkedBlockingQueue<Runnable>()) );  
 8 }  
 9 //使用  
10 Executors.newSingleThreadPool ().execute(r);  

(1)從配置參數能夠看出,SingleThreadPool只有一個核心線程,確保全部任務都在同一線程中按順序完成。所以不須要處理線程同步的問題。

(2)【前方高能,筆者腦洞】能夠把SingleThreadPool簡單的理解爲FixThreadPool的參數被手動設置爲1的狀況,即Executors.newFixThreadPool(1).execute(r)。因此SingleThreadPool能夠理解爲公廁裏只有一個坑位,先來先上。爲何只有一個坑位呢,由於這個公廁是收費的,收費的大爺上年紀了,只能管理一個坑位,多了就管不過來了(線程同步問題)。

 

2.3     CachedThreadPool(一堆人去一家很大的咖啡館喝咖啡)

 1 /* 
 2 *@CachedThreadPool介紹 
 3 *@author SEU_Calvin 
 4 * @date 2016/09/03 
 5 */  
 6 public static ExecutorService newCachedThreadPool(int nThreads){  
 7     return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit. SECONDS, new SynchronousQueue<Runnable>());  
 8 }  
 9 //使用  
10 Executors.newCachedThreadPool().execute(r);  

(1)CachedThreadPool只有非核心線程,最大線程數很是大,全部線程都活動時,會爲新任務建立新線程,不然利用空閒線程(60s空閒時間,過了就會被回收,因此線程池中有0個線程的可能)處理任務。

(2)任務隊列SynchronousQueue至關於一個空集合,致使任何任務都會被當即執行。

(3)【前方高能,筆者腦洞】CachedThreadPool就像是一堆人去一個很大的咖啡館喝咖啡,裏面服務員也不少,隨時去,隨時均可以喝到咖啡。可是爲了響應國家的「光盤行動」,一我的喝剩下的咖啡會被保留60秒,供新來的客人使用,哈哈哈哈哈,好惡心啊。若是你運氣好,沒有剩下的咖啡,你會獲得一杯新咖啡。可是之前客人剩下的咖啡超過60秒,就變質了,會被服務員回收掉。

(4)比較適合執行大量的耗時較少的任務。喝咖啡人挺多的,喝的時間也不長。

 

 

2.4    ScheduledThreadPool(4個裏面惟一一個有延遲執行和週期重複執行的線程池)

 1 /* 
 2 *@ScheduledThreadPool介紹 
 3 *@author SEU_Calvin 
 4 * @date 2016/09/03 
 5 */  
 6 public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize){  
 7 return new ScheduledThreadPoolExecutor(corePoolSize);  
 8 }  
 9 public ScheduledThreadPoolExecutor(int corePoolSize){  
10 super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedQueue ());  
11 }  
12 //使用,延遲1秒執行,每隔2秒執行一次Runnable r  
13 Executors. newScheduledThreadPool (5).scheduleAtFixedRate(r, 1000, 2000, TimeUnit.MILLISECONDS);

(1)核心線程數固定,非核心線程(閒着沒活幹會被當即回收)數沒有限制。

(2)從上面代碼也能夠看出,ScheduledThreadPool主要用於執行定時任務以及有固定週期的重複任務。

 

至此Android中最多見的四類不一樣特性的線程池內容總結完畢。

轉載請註明出處:http://blog.csdn.net/seu_calvin/article/details/52415337

相關文章
相關標籤/搜索