每一個 Android 應用進程在建立時,會同時建立一個線程,咱們稱之爲主線程,負責更新 UI 界面以及和處理用戶之間的交互,所以,在 Android 中,咱們又稱之爲 UI 線程。一個進程中 UI 線程只有一個,爲了避免形成界面卡頓、提升用戶體驗,咱們勢必要將一些耗時操做交由子線程來執行。html
使用子線程的方式主要分兩種:java
線程池是什麼linux
線程池是指在初始化一個多線程應用程序過程當中建立一個線程集合,而後在須要執行新的任務時重用這些線程而不是新建立一個線程。線程池中線程的數量一般徹底取決於可用內存數量和應用程序的需求;每一個線程都有被分配一個任務,一旦任務完成了,線程回到池子中並等待下一次分配任務。 android
通常狀況下,推薦使用線程池來建立和使用子線程,不建議使用第一種方式。多線程
上面說了,在 Android 開發過程當中,建議使用線程池來建立和使用子線程,那麼使用線程池的好處有哪些呢?異步
Android 中線程池的真正實現是 ThreadPoolExecutor,其構造方法有 5 個,經過一系列參數來配置線程池。下面介紹一個比較經常使用的構造方法及其參數的含義。函數
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)
參數 | 含義 |
---|---|
corePoolSize |
int : 線程池的核心線程數,默認狀況下,核心線程回一直在線程池中存活,即便他們處於閒置狀態。若是將 allowCoreThreadTimeOut 的屬性設置爲 true,那麼閒置的核心線程在等待新任務到來時會有超時策略,這個時間間隔由 keepAliveTime 所指定,當等待時間超過 keepAliveTime 所指定的時長後,核心線程就會被終止。 |
maximumPoolSize |
int : 線程池中容許的線程最大數量,當活動線程達到這個數值後,後續的新任務會被阻塞。 |
keepAliveTime |
long : 非核心線程閒置時的超時時長,超過這個時長,非核心線程就會被回收。當 allowCoreThreadTimeOut 屬性被設置爲 true 時,該參數一樣會做用於核心線程。 |
unit |
TimeUnit : keepAliveTime 參數的時間單位 ,參數爲 TimeUnit 的枚舉,常見的有 TimeUnit.MILLISECONDS (毫秒)、TimeUnit.SECOND (秒) 等。 |
workQueue |
BlockingQueue : 線程池中的任務隊列,經過線程池的 execute 方法提交的 Runnable 對象會存儲在這個參數中。 |
threadFactory |
ThreadFactory : 建立線程的線程工廠。ThreadFactory 是一個接口,只有一個方法:Thread newThread (Runnable r) |
Throws | |
---|---|
IllegalArgumentException |
符合如下任一條件,則拋出此異常: corePoolSize < 0 keepAliveTime < 0 maximumPoolSize <= 0 maximumPoolSize < corePoolSize |
NullPointerException |
當 workQueue 或者 threadFactory 爲 null 時,拋出此異常。 |
ThreadPoolExecutor 執行任務時大體遵循以下規則:性能
RejectedExecutionHandler 是線程池持有的一個對象,用於不能由 ThreadPoolExecutor 執行的任務的處理
Android 中最多見線程池有四種,分別是:FixedThreadPool、CacheThreadPool、ScheduledThreadPool 以及 SingleThreadPool,它們都直接或間接的經過配置 ThreadPoolExecutor 來實現本身的功能特性。優化
線程數量固定的線程池,經過 Executors 的 newFixedThreadPool 方法建立。有兩個重載的建立方法:google
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory); }
除非線程池被關閉,不然線程不會被回收,即時線程處於空閒狀態。若是在全部線程都處於活動狀態時提交額外的任務,它們將在隊列中等待,直到有一個線程可用爲止。由建立方法可知,FixedThreadPool 只有核心線程而且這個核心線程沒有超時機制(keepAliveTime 參數爲 0L),加上線程不會被回收,所以使用此類線程池能夠快速地響應外界的請求。
線程數量不定的線程池,經過 Executors 的 newCachedThreadPool 方法建立。有兩個重載的建立方法:
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(/* corePoolSize*/ 0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { return new ThreadPoolExecutor(/* corePoolSize*/ 0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory); }
CacheThreadPool 有如下個特徵:
核心線程數量固定,非核心線程數量不定的線程池,經過 Executors 的 newscheduledthreadpool 方法建立。有兩個重載的建立方法:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
public static ScheduledExecutorService newScheduledThreadPool( int corePoolSize, ThreadFactory threadFactory) { return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); }
ScheduledThreadPool 相比較其餘三種線程池,有特殊性,由 ScheduledThreadPoolExecutor 實現, newscheduledthreadpool 方法也是經過建立 ScheduledThreadPoolExecutor 的實例來完成線程池的建立,代碼以下:
public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, new DelayedWorkQueue()); }
public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) { super(corePoolSize, Integer.MAX_VALUE, DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, new DelayedWorkQueue(), threadFactory); }
由 ScheduledThreadPoolExecutor 的構造函數可知, ScheduledThreadPool 的核心線程數量是固定的,由傳入的 corePoolSize 參數決定,非核心線程數量能夠無限大。非核心線程閒置回收的超時時間爲 10秒( DEFAULT_KEEPALIVE_MILLIS 的值爲 10L )。這類線程主要用於執行定時任務或者具備週期性的重複任務。
只有一個核心線程,經過 Executors 的 newsinglethreadexecutor 方法建立。有兩個重載的建立方法:
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(/* corePoolSize*/ 1, /* maximumPoolSize*/ 1, /* keepAliveTime*/ 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(/* corePoolSize*/ 1, /* maximumPoolSize*/ 1, /* keepAliveTime*/ 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory)); }
SingleThreadPool 由 代理類 FinalizableDelegatedExecutorService 建立。該線程池只有一個線程(核心線程),而且該線程池的任務隊列是無上限的,這就確保了全部的任務都在同一個線程中順序執行。
注意,若是因爲在執行期間出現故障而致使該線程終止,那麼若是須要執行後續任務,則新線程將取而代之。
上面分別對 Android 中常見的 4 種線程池進行了簡單的介紹,除了這 4 種系統提供的線程池外,咱們在使用的過程當中,也能夠根據須要直接經過 ThreadPoolExecutor 的構造函數來靈活的配置線程池。那麼,上述的 4 種線程池,其區別在哪呢?瞭解其區別有助於咱們去選擇更爲合適的線程池或者直接經過 ThreadPoolExecutor 來配置更靈活的線程池。
FixedThreadPool 線程固定,且不會被回收,可以更快的響應外界請求。
CachedThreadPool 只有非核心線程,且線程數至關於無限大,任何任務都會被當即執行。比較適合執行大量的耗時較少的任務。
ScheduledThreadPool 主要用於執行定時任務或者具備週期性的重複任務。
SingleThreadPool 只有一個核心線程,確保全部任務都在同一線程中按順序完成。所以不須要處理線程同步的問題。