AsyncTask 隨著 Android SDK 的更新,也改變了幾次設定。在
Android 1.5(CUPCAKE) 中,
AsyncTask 是 Single Thread,一個 task 接著一個 task 執行;從
Android 1.6(DONUT) 一直到
Android 2.3(GINGERBREAD),AsyncTask 變成了 Multi-Thread,當 tasks 剛好等於 5 個時,
最多就可以同時執行 5 個 threads (CORE_POOL_SIZE=5) 來完成 tasks,如果又多 1 個 task,
就會放到 queue 裡,這個 queue 的大小為 10,直到 queue 放不下時,才會在建立一個 thread
來處理新進的 task,最多可有 128 (MAXIMUM_POOL_SIZE) 個 threads 同時處理 tasks,而
tasks 最多可有 128+10=138 個,超過時會發生
java.util.concurrent.RejectedExecutionException。
以上所提到的定義值,可在 AsyncTask.java 的原始碼中看到:
// Source code of Android 4.2.1 r.1.2
public abstract class AsyncTask <Params, Progress, Result> {
private static final String LOG_TAG = "AsyncTask";
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 1;
...
private static final BlockingQueue<runnable> sPoolWorkQueue =
new LinkedBlockingQueue<runnable>(10);
...
Android 4.4 之後,CORE_POOL_SIZE 改為 CPU_COUNT+1,MAXIMUM_POOL_SIZE 改為 CPU_COUNT*2+1,queue 的大小改為 128,所以 threads 變少了(猜想應該是為了效能的關係),queue 變大了。
// Source code of Android 4.4 r1
// http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/android/os/AsyncTask.java#AsyncTask
public abstract class AsyncTask <Params, Progress, Result> {
private static final String LOG_TAG = "AsyncTask";
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE = 1;
...
private static final BlockingQueue<runnable> sPoolWorkQueue =
new LinkedBlockingQueue<runnable>(128);
...
從
Android 3.0(HONEYCOMB) 之後又改回了 Single Thread。Single Thread 版本的 tasks 最多
大小則取決於記憶體,因為是使用 ArrayDeque 來存放 tasks:
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() {
...
另外,想要使用之前 Multi-Thread 的版本就要呼叫
executeOnExecutor(THREAD_POOL_EXECUTOR, Object []),而不是原本的 execute。
參考資料:
- http://developer.android.com/reference/android/os/AsyncTask.html
- http://blog.csdn.net/hitlion2008/article/details/7983449
- http://stackoverflow.com/questions/4068984/running-multiple-asynctasks-at-the-same-time-not-possible
- http://stackoverflow.com/questions/10480599/how-asynctask-works-in-android