引言
Android的線程池概念來自于Java的Executor,真正的線程池實作為ThreadPoolExecutor。在Android中,提供了4類不同的線程池,具體下面會說到。為什麼使用線程池呢?而不是使用Thread建立線程呢?因為使用線程池有以下幾個優點:
- 重用線程池的線程,避免因為線程的建立和銷毀所帶來的性能開銷
- 能有效控制線程池的最大并發數,避免線程之間搶占資源導緻阻塞
- 能夠對線程進行簡單的管理,并提供定時執行以及指定間隔循環執行等功能
是以需要多次建立Thread時使用線程池較好。
ThreadPoolExecutor
它是線程池的真正實作,構造函數提供一系列的參數配置線程池。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
- corePoolSize:核心線程數,預設情況下,即時處于閑置狀态下,核心線程會線上程一直存活;如果設定allowCoreThreadTimeOut為true,閑置的核心線程等待任務期間會有逾時政策,時間間隔由keepAliveTime設定,最大為CPU核心數+1
- maximumPoolSize:線程池容納最大線程數,當活動線程數超過這個數值,後續的新任務會導緻阻塞,最大為CPU核心數2倍+1
- keepAliveTime:非核心線程閑置時逾時的時長,如果設定allowCoreThreadTimeOut為true,即作用于閑置的核心線程
- unit:時間機關,使用TimeUnit枚舉
- workQueue:線程池中的任務隊列,通過線程池execute方法送出Runnable對象會存儲這個參數中,容量為128
- threadFactory:線程工廠,為線程池提供建立新線程的功能
- handler:線程池對拒絕任務的處理政策。一般是隊列已滿或者無法成功執行任務,這時ThreadPoolExecutor會調用handler的rejectedExecution方法來通知調用者,有四個政策:
- ThreadPoolExecutor.AbortPolicy() 直接抛出異常RejectedExecutionException
- ThreadPoolExecutor.CallerRunsPolicy() 直接調用run方法并且阻塞執行
- ThreadPoolExecutor.DiscardPolicy() 直接丢棄後來的任務
- ThreadPoolExecutor.DiscardOldestPolicy() 丢棄在隊列中隊首的任務
執行任務規則可用currentSize表示線程池中目前線程數量,将上述過程可以表示如下
- 當currentSize < corePoolSize時,直接啟動一個核心線程并執行任務
- 當currentSize>=corePoolSize、并且workQueue未滿時,添加進來的任務會被安排到workQueue中等待執行
- 當workQueue已滿,但是currentSize<maximumPoolSize時,會立即開啟一個非核心線程來執行任務
- 當currentSize>=corePoolSize、workQueue已滿、并且currentSize>maximumPoolSize時,調用handler預設抛出RejectExecutionExpection異常
- 當currentSize >corePoolSize線程,空閑時間達到keepAliveTime時,關閉空閑線程
- 當設定allowCoreThreadTimeOut(true)時,線程池中corePoolSize線程空閑時間達到keepAliveTime也将關閉
FixedThreadPool
通過Executors的newFixedThreadPool方法建立,它是一種線程數量固定的線程池,當線程處于空閑狀态時,它們并不會被回收,除非線程池被關閉了。當所有的線程都處于活動狀态時,新任務都會處于等待狀态,直到有線程空閑出來。由于FixedThreadPool隻有核心線程并且這些核心線程不會被回收,這意味着它能夠更加快速地響應外界的請求。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
CachedThreadPool
通過Executors的newCachedThreadPool方法建立,它是一種線程數量不定的線程池,它隻有非核心線程,并且最大線程數為Integer.MAX_VALUE,從CachedThreadPool的特性來看,這類線程池比較适合執行大量的耗時較少的任務,當整個線程池都處于閑置狀态時,線程池中的線程都會逾時而被停止,這個時候CachedThreadPool之中實際上是沒有任何線程的,它幾乎是不占用任何系統資源的。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
ScheduledThreadPool
通過Executors的newScheduledThreadPool方法建立,它的核心線程是固定的,非核心線程數是沒有限制的,主要用于執行定時任務和具有固定周期的重複任務。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
SingleThreadExecutor
通過Executors的newSingleThreadExecutor方法建立,它隻有一個核心線程,確定所有任務都在同一個線程中按順序執行,使得這些不需要處理線程同步問題。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}