其實平常做專案滿少直接使用到Thread Pool,大部分專案規模都不大,難度也不高,沒有特別複雜的計算或耗時的操作,最常見的幾乎都是刻UI,Call API。但不管是Call API、或是處理圖片等耗時的行為幾乎也都有套件完美做完了,不過總是不能一輩子用別人做好的套件,總是有需要獨當一面的時候。
這邊我們就討論一下呼叫API或者處理圖片基本上都該會用到的底層行為Thread。
Android原生可用的ThreadPool有幾種,分別是FixedThreadPool、ScheduledThreadPool、CachedThreadPool、SingleThreadExecutor
FixedThreadPool
特性:算是一個基本款的Thread Pool,可以限制同時執行的Thread數量
使用方式如下,newFixedThreadPool帶入的參數就是可同時執行的數量,所以這邊就是最多同時執行兩個Thread
假設一開始執行了四個,頭兩個會先跑,剩下的兩個會等待前面的結束後才逐一補上
ExecutorService mFixedThreadPool = Executors.newFixedThreadPool(2);
mFixedThreadPool.execute(new MyRunnable());
ScheduledThreadPool
特性:可做排程、週期性執行
newScheduledThreadPool同樣是帶入可同時執行的Thread數量,scheduleAtFixedRate/scheduleWithFixedDelay兩者規則不同,使用時要注意一下需求
ScheduledExecutorService mScheduledThreadPool = Executors.newScheduledThreadPool(2);
mScheduledThreadPool.execute(new MyRunnable());
or
//延後500毫秒執行
mScheduledThreadPool.schedule(new MyRunnable(), 500, TimeUnit.MILLISECONDS);
or
//延後1秒執行,每3秒執行一次
mScheduledThreadPool.scheduleAtFixedRate(new MyRunnable(), 1, 3, TimeUnit.SECONDS);
or
//延後1秒執行,每次執行完後等待3秒執行下一次
mScheduledThreadPool.scheduleWithFixedDelay(new MyRunnable(), 1, 3, TimeUnit.SECONDS);
CachedThreadPool
特性:沒有限制數量,Thread在沒有使用時會被回收,60秒內可被重新使用,如果都沒有已回收的執行緒則創建新的
ExecutorService mCacheThreadPool = Executors.newCachedThreadPool();
mCacheThreadPool.execute(new MyRunnable());
SingleThreadExecutor
特性:只用單一個Thread執行
ExecutorService mSingleThreadExecutor = Executors.newSingleThreadExecutor();
mSingleThreadExecutor.execute(new MyRunnable());
看完基本介紹後可能會覺得,好像除了ScheduledThreadPool以外,其他的看不出什麼特別明顯的差異
所以這邊就來比較一下,除了ScheduledThreadPool以外其他三個Thread Pool實際跑起來的差別
首先我們創建一個客製化的Runnable,Log一下當下Thread的名稱以及初始化的順序標記
在使用FixedThreadPool時,每個Runnable所屬的Thread名稱是不同的
接下來是CachedThreadPool,pool-1-thread-1 ~ 3重複使用了兩次,符合上面我們所說的,由於每個Runnable需要至少一秒才能執行完,所以幾乎同時執行order 01~03時創建了三組新的Thread(1~3),但等待兩秒後執行order 04~06時,原本的pool-1-thread-1 ~ 3已經都執行完了,馬上拿來重複利用
再來我們測試另一個狀態的CachedThreadPool,這邊故意等待超過60秒再執行order 04~06,就必須要再創建新的Thread
最後是SingleThreadExecutor,執行01~06全都在同一個Thread上,仔細看一下Log時間,每一個間隔幾乎可以說是一秒,可以發現這邊可能會發生阻塞、等待的問題
實作完之後我個人對於Thread Pool應用時機上有大概抓到方向,提供我個人的意見讓大家參考
FixedThreadPool
ScheduledThreadPool
CachedThreadPool
SingleThreadExecutor
至於一開始提到的Call API,處理圖片讀取、緩存、二階段緩存等,應該會先使用CachedThreadPool試試看,第二人選則是FixedThreadPool
以上純屬我個人想法,有任何意見、指正或者實際使用案例歡迎分享討論