(源碼來自sdk7.0)
構造方法
構造方法有3個
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
this((Looper) null);
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide
*/
public AsyncTask(@Nullable Handler handler) {
this(handler != null ? handler.getLooper() : null);
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide
*/
public AsyncTask(@Nullable Looper callbackLooper) {
第3個構造是主要構造,但被隱藏了。應用層常用到的是無參構造即傳入一個null至該構造,實際等價於傳入MainLooper。
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide
*/
public AsyncTask(@Nullable Looper callbackLooper) {
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
但是這裏的主線程looper和非主線程looper實際上是分開處理的,非主線程需要自己處理不同message的結果的分發,而主線程的源碼中完全替你封裝好了。
主線程的mHandler初始化getMainHandler
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
這個InternalHandler就是做了MESSAGE_POST_RESULT和MESSAGE_POST_PROGRESS的主線程回調
因爲靜態內部類在假泛型中無法獲取到泛型類型,而暴露給API的
protected void onProgressUpdate(Progress... values)
protected void onPostExecute(Result result)
顯然希望使用到泛型約束。這裏不得已用了unchecked屏蔽編譯錯誤。因爲每個AsyncTask的只能執行一次,這裏的類型安全是沒問題的~~~ 就是代碼可讀性稍差,
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@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]); //主線程調用被複寫的onCancel或者onPostExecute
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData); //主線程調用被複寫的onProgressUpdate
break;
}
}
}
構造方法中除了創建了handler,更重要的是初始化了FutureTask
mWorker = new WorkerRunnable<Params, Result>() { //WorkRunnable其實就是個Callback的實現,靜態內部類存放Params規避內存泄漏
public Result call() throws Exception {
mTaskInvoked.set(true); //mTaskInvoked在call第一行用於標識任務已經被執行。在done中調用postResultIfNotInvoked提取判斷
//因爲done()函數如果在future的cancel時是由調用線程執行的 可能存在線程安全問題
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams); //子線程執行執行復寫的doInBackground任務
Binder.flushPendingCommands(); //以下是該靜態函數的api註釋
/*將當前線程中掛起的所有Binder命令都刷新到內核驅動。
這可以在執行可能阻塞很長時間的操作之前調用,
以確保任何掛起的對象引用已經被釋放。
這樣可以防止這一耗時過程的持續時間超過對象應有的生命週期。*/
} catch (Throwable tr) {
mCancelled.set(true); //這裏也是一個AtomicBoolean 標識cancel
throw tr;
} finally {
postResult(result);//mTaskInvoked被設置爲true這句代碼執行之後,就保證了final中調用postResult
}
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());//future阻塞get()獲取result 並根據拋出的異常處理狀態
} 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);
}
}
}
這裏有個小疑問,mTaskInvoked是一個AtomicBoolean,保證多線程的原子性,但是這裏並沒有調用compareAndSet方法,那麼使用原子類的意義在哪裏呢? 這裏在我的理解裏 應該只需要聲明volatile boolean mTaskInvoked就可以了,如有高見歡迎討論。
postResultIfNotInvoked函數的意義,當future沒有執行就被cancel後,cancel調用done()函數,獲得到get()將是一個空,這時進入!wasTaskInvoked流程 postResult(null)
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
線程調度
異步任務啓動的入口
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) { //這段代碼保證AsyncTask只能被執行一次
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; //配置參數給Callback
exec.execute(mFuture); //全局調度執行器 接管futrue
return this;
}
不管我們通常調用的execute(Params... params)還是提供給我們直接運行一個runnable的
@MainThread
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
實際都是使用全局調度執行器sDefaultExecutor進行處理,它的默認實現是一個串行的分發
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
在主線程調用
並且他的實現保證了串行:全局中多個AsyncTask被execute,只會有deque頭部那個成爲mActive,依序執行
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() { //offer插入ruunable到deque的尾部
//代理包裝了r 實際執行是由線程池做的 這裏只是添加了 調度工作的代理層
public void run() {
try { //這樣try catch 不阻礙異常的拋出 同時又能保證 一個runnable執行完之後 一定執行下一個
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) { //塞進隊列後檢查:如果現在沒有執行的runnable 那麼開始幹活了
scheduleNext();
}
}
protected synchronized void scheduleNext() { //這個函數執行時機在1、deque從空到有時 與2、sWorkExecutor有runnable執行完畢時調用
if ((mActive = mTasks.poll()) != null) { //頭部取出 開始執行
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
線程池
我們看到了真正消費mTasks中的Runnable的是THREAD_POOL_EXECUTOR.execute(mActive)
他是一個全局的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;
}
他也是public的 可以直接設置。缺省值爲一個核心線程cpu-1、最大線程2倍cpu、非核心線程待活時間10秒、等待工作隊列長度128的線程池
超出工作隊列的拒絕策略用的是java缺省的拋異常RejectedExecutionException
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
可以關注一下線程工廠的計數器 用的是原子類AtomicInt的自增
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};