針對android中的多執行緒請求,本文主要介紹 android中執行緒池的基本使用。
1:執行緒池的分類
FixedThreadPool:它是一種執行緒數量固定的執行緒池,當執行緒處於空閒狀態時,它們並不會被回收,除非執行緒池被關閉,當所有的執行緒都處於活動狀態時,新任務都會處於等待狀態,直到有執行緒空閒出來。該執行緒池中只有核心執行緒,並且這些核心執行緒不會被回收,這意味著它能夠更加快速的響應外界的請求。
CachedThreadPool: 該執行緒池中執行緒數量不固定,並且內部只有非核心執行緒,其執行緒的最大值為 Integer.MAX_VALUE。所以可以認為該執行緒池中的執行緒數量可以任意大。該執行緒池的特定是當執行緒池中的執行緒都處於活動狀態時,執行緒池會建立新的執行緒來處理新的任務,否則就會利用空閒的執行緒來處理新的任務。該執行緒池中的空閒執行緒都有超時機制,這個超時時長為 60s ,超過60s 空閒執行緒就會被回收。
ScheduledThreadPool: 該執行緒池中包含核心執行緒以及非核心執行緒,核心執行緒數量是固定的,而非核心執行緒數量是沒有限制的,並且當非核心執行緒閒置時會被立即回收。
SingleThreadExecutor:該執行緒池是一個單例執行緒,其內部只有一個核心執行緒。
2:執行緒池的基本使用
FixedThreadPool:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4)
fixedThreadPool.execute(runnable)複製程式碼
CachedThreadPool:
ExecutorService cacheThreadPool = Executors.newCachedThreadPool()
cacheThreadPool.execute(runnable)複製程式碼
ScheduledThreadPool:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4)
scheduledThreadPool.schedule(runnable3, 2000, TimeUnit.MILLISECONDS)複製程式碼
SingleThreadExecutor:
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor()
singleThreadExecutor.execute(runnable)複製程式碼
2:執行緒池的基本使用
FixedThreadPool:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4)
fixedThreadPool.execute(runnable)複製程式碼
CachedThreadPool:
ExecutorService cacheThreadPool = Executors.newCachedThreadPool()
cacheThreadPool.execute(runnable)複製程式碼
ScheduledThreadPool:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4)
scheduledThreadPool.schedule(runnable3, 2000, TimeUnit.MILLISECONDS)複製程式碼
SingleThreadExecutor:
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor()
singleThreadExecutor.execute(runnable)複製程式碼
3: 執行緒池構造解析
android中執行緒池概念來源於java中的Executor,而Executor通過原始碼我們可以看出是一個介面;
public interface Executor {
void execute(Runnable command);
}
複製程式碼
內部只包含一個抽象方法 execute(….);
同時android中 重新定義了ExecutorService介面去繼承上述介面;
public interface ExecutorService extends Executor{}複製程式碼
而 ExecutorService 介面的實現類是:
public abstract class AbstractExecutorService implements ExecutorService{}複製程式碼
抽象類AbstractExecutorService 的具體實現是:
public class ThreadPoolExecutor extends AbstractExecutorService{}複製程式碼
通過上述關係可以看到執行緒池的真正實現為ThreadPoolExecutor,在ThreadPoolExecutor 中提供了一系列的引數來建立不同的執行緒池。
下面我們來看ThreadPoolExecutor的建構函式:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {}複製程式碼
內部引數:
corePoolSize:執行緒的核心執行緒數;
maximumPoolSize:執行緒池所能容納的最大執行緒數:
keepAliveTime:非核心執行緒閒置時的超時市場,超過這個時長非核心執行緒就會被回收
unit:用於指定keepAliveTime 的單位
workQueue:執行緒池中的任務佇列
threadFactory:執行緒工廠,為執行緒池提供建立新執行緒的功能
handler:當執行緒池無法執行新的任務時,會呼叫handler的rejectedEcexutor方法來通知呼叫者。該引數不常用,可以忽略。
通過原始碼我們可以看到google是通過工廠方式去建立各種執行緒池,具體原始碼我們可以通過
public class Executors{}複製程式碼
該類可以看到內部通過各種方法去獲取不同的執行緒池。
下面我們根據Executors 中各個方法去看各個執行緒池是如何實現的。
FixedThreadPool:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}複製程式碼
FixedThreadPool 通過呼叫 ThreadPoolExecutor建構函式 可以看出實質上是通過外部設定了 核心執行緒數,以及非核心執行緒數。
CachedThreadPool:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}複製程式碼
CachedThreadPool 內部可以看出實質上 核心執行緒數為0 ,而非核心執行緒數為Int最大值
SingleThreadExecutor:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue()));
}複製程式碼
SingleThreadExecutor 可以看出實質上是核心執行緒數以及非核心執行緒數均為1;
ScheduledThreadPool:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public class ScheduledThreadPoolExecutor
extends ThreadPoolExecutor
implements ScheduledExecutorService {
....
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
....
}複製程式碼
ScheduledThreadPool 可以看出核心執行緒數是通過外部設定,而非核心執行緒數實質是int的最大值。
4 : 執行緒池的基本執行流程
1:如果執行緒池中核心執行緒未達到上限那麼,則會直接啟動一個核心執行緒去執行任務;
2:如果核心執行緒達到上限,那麼會將任務放到任務佇列中,等待執行,
3:如果任務無法插入到任務佇列中,則會開啟一個非核心執行緒去執行任務,
4:如果執行緒池中的執行緒已經達到執行緒數量的上限,則將不會去執行任務,ThreadPoolExecutor將會呼叫RejectedExecutionHandler的rejectedExecution方法通知呼叫者。
以下通過圖示來說明: