看過OKHTTP源碼的都會知道,裏面有個任務調度Dispatcher
這裏分析一下Dispatcher源碼:
public final class Dispatcher {
private int maxRequests = 64;//最大請求數
private int maxRequestsPerHost = 5;//最大主機數
private @Nullable Runnable idleCallback;//空閒回調
private @Nullable ExecutorService executorService;//線程池
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();//等待執行隊列
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();//正在執行隊列(異步)
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();//正在執行隊列(同步)
//創建線程池
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
***省略代碼
//入隊
void enqueue(AsyncCall call) {
synchronized (this) {
readyAsyncCalls.add(call);
}
promoteAndExecute();
}
//取消所有請求
public synchronized void cancelAll() {
for (AsyncCall call : readyAsyncCalls) {
call.get().cancel();
}
for (AsyncCall call : runningAsyncCalls) {
call.get().cancel();
}
for (RealCall call : runningSyncCalls) {
call.cancel();
}
}
//啓動並執行
private boolean promoteAndExecute() {
assert (!Thread.holdsLock(this));
List<AsyncCall> executableCalls = new ArrayList<>();
boolean isRunning;
synchronized (this) {
//遍歷異步隊列
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall asyncCall = i.next();
//判斷是否超過最大值
if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.
i.remove();
executableCalls.add(asyncCall);
runningAsyncCalls.add(asyncCall);
}
isRunning = runningCallsCount() > 0;
}
//遍歷可執行隊列,並執行
for (int i = 0, size = executableCalls.size(); i < size; i++) {
AsyncCall asyncCall = executableCalls.get(i);
asyncCall.executeOn(executorService());
}
return isRunning;
}
//加入同步隊列
synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
//當前線程結束時,執行空閒回調
private <T> void finished(Deque<T> calls, T call) {
Runnable idleCallback;
synchronized (this) {
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
idleCallback = this.idleCallback;
}
boolean isRunning = promoteAndExecute();
if (!isRunning && idleCallback != null) {
idleCallback.run();
}
}
***省略代碼
}
代碼中可以看出,Dispatcher利用三個隊列來維持線程池的調度