AsyncTask是一個很方便用來在主線程和工作線程切換任務的工具,但是如果用的不好會引入不少奇怪的問題
坑1:AsyncTask到底是并行還是串行
在回答這個 問題前,我們先看下官方對AsyncTask的注釋,對AsyncTask有一個基本的了解
AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler} * and does not constitute a generic threading framework. AsyncTasks should ideally be * used for short operations (a few seconds at the most.) If you need to keep threads * running for long periods of time, it is highly recommended you use the various APIs * provided by thejava.util.concurrentpackage such as {@link Executor}, * {@link ThreadPoolExecutor} and {@link FutureTask}
從上面AsyncTask源碼注釋可以看出,AsyncTask只適合做短時間操作的任務(頂多幾秒),長時間的操作不建議使用,但是why?
首先我們來看下最基礎的AsyncTask的運行模型
對于一個AsyncTask任務執行時3個關鍵函數運行的環境如上圖所示,這個沒有太多的疑問。
那如果多個AsyncTask同時執行會有啥不一樣的么?
先上結論:
同一進程內,多個AsyncTask 直接通過execute方法執行時,在android3.0以上是串行的
這就解答了源碼注釋里面的一個疑問,為什么AsyncTask只適合做短時間的操作。
因為他是串行執行的,如果前面的AsyncTask阻塞了,后面的AsyncTask就全部阻塞了。。。。。(多么痛的領悟)
我們來一起捋一捋代碼,看看為啥得出這樣的結論
作為一個可以提交多個任務 ,且可以在工作線程和主線程切換的工具類,必須有以下幾個組成
1.線程池
2.事件隊列
3.handler
先看線程池
一個最簡單的AsyncTask方法寫法應該是
new AsyncTask().execute();
我們看下execute方法的源碼如下
里面有個sDefaultExecutor,一看就是一個線程池,我們來看下定義
線程池是一個靜態變量,也就是說對于同一個進程來說,只會初始化一次,同一進程內的AsyncTask都運行在此進程池中。
真相大白了,從任務隊列中一個個取出任務,執行完了再scheduleNext(),串行的執行任務。所以說千萬不要在AsyncTask中執行長時間的任務