之前開發(fā)中經(jīng)常使用AsyncTask進(jìn)行異步數(shù)據(jù)獲取内边,當(dāng)時只限于使用榴都,具體的代碼細(xì)節(jié)沒有仔細(xì)看過,今天就閱讀一下源碼漠其,當(dāng)作筆記嘴高。加深記憶
構(gòu)造函數(shù)
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result);
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
首先看WorkerRunnable,實現(xiàn)了Callable接口
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
再看一下首先看WorkerRunnable的初始化和屎,由于是一個抽象類拴驮,需要實現(xiàn)內(nèi)部方法,具體方法里面的實現(xiàn)是將mTaskInvoked設(shè)置為true柴信,然后調(diào)用doInBackground方法套啤,然后將doInBackground返回的結(jié)果集傳參給postResult方法并返回。
我們看一下postResult方法到底是個什么
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
postResult方法內(nèi)部創(chuàng)建了一條消息随常,message.what=MESSAGE_POST_RESULT,message.obj=new AsyncTaskResult<Result>(this, result),然后通過異步消息機制將消息傳遞出去潜沦。
那我們傳遞出去的obj又是個什么呢
private static class AsyncTaskResult<Data> {
final AsyncTask mTask;
final Data[] mData;
AsyncTaskResult(AsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
一個很普通的類,就是將傳入的參數(shù)保存一下
我們看一下處理消息的handler
private static Handler getHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler();
}
return sHandler;
}
}
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
看handleMessage方法绪氛,接收到之前的what參數(shù)MESSAGE_POST_RESULT,執(zhí)行finish方法唆鸡,我們看一下finish方法干了哪些事
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
邏輯很簡單,判斷任務(wù)是否取消枣察,如果取消就執(zhí)行onCancelled方法争占,如果沒有取消就onPostExecute袄琳,最后將狀態(tài)更改為結(jié)束狀態(tài)
我們在次回到構(gòu)造方法中,WorkerRunnable初始化完成之后開始進(jìn)行FutureTask的任務(wù)初始化燃乍,將mWorker當(dāng)做構(gòu)造參數(shù)傳入唆樊,覆寫done方法
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
在mWorker中的任務(wù)執(zhí)行完畢之后會執(zhí)行postResultIfNotInvoked方法,我們接著再看一下這個方法發(fā)生了什么:
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
方法也比較簡單刻蟹,會去判斷mTaskInvoked的true或false逗旁,mWorker執(zhí)行完畢之后已經(jīng)將mTaskInvoked設(shè)置了為true,所以if里面的語句一般是執(zhí)行不到的
任務(wù)執(zhí)行
到這異步任務(wù)的初始化分析已經(jīng)完成了舆瘪,接著異步任務(wù)初始化完成之后我們需要去執(zhí)行他片效,也就是execute方法:
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
方法內(nèi)部其實是調(diào)用了executeOnExecutor方法,我們再看一下這個方法:
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
看核心部分exec.execute(mFuture)英古,exec指向的是一個SerialExecutor實例
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
在SerialExecutor內(nèi)部維護(hù)了一個任務(wù)隊列淀衣,通過offer方法將任務(wù)添加到隊尾,任務(wù)執(zhí)行完之后調(diào)用scheduleNext方法召调,scheduleNext方法內(nèi)部將任務(wù)隊列的隊首任務(wù)取出膨桥,如果不為空的話就通過THREAD_POOL_EXECUTOR去執(zhí)行這個任務(wù)
這個THREAD_POOL_EXECUTOR又是什么呢
public static final Executor THREAD_POOL_EXECUTOR;
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
通過靜態(tài)塊去初始化了一個線程池,看一下線程池的參數(shù)
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);
理想情況下核心線程數(shù)為4個唠叛,最大線程并發(fā)數(shù)是CPU數(shù)乘以2然后減1只嚣,最大支持4*2+1=9個的線程數(shù),空閑線程存活時間為30S艺沼,然后還有一個長度128的線程隊列册舞,當(dāng)我們有多個任務(wù)需要執(zhí)行execute的時候,execute方法是一個同步方法障般,第一個任務(wù)入隊调鲸,由poll取出執(zhí)行,第二個任務(wù)需要等待第一個任務(wù)執(zhí)行完畢之后才能執(zhí)行挽荡,所以execute方法是任務(wù)串行藐石。
在開發(fā)中大部分的情況是并行的,又要怎么樣才能進(jìn)行并行操作呢徐伐,我們可以直接使用executeOnExecutor方法執(zhí)行任務(wù)贯钩,只需要指定一個線程池跟參數(shù)即可,我們可以用源碼中提供的THREAD_POOL_EXECUTOR办素,這樣就可以實現(xiàn)任務(wù)的并行。