This page looks best with JavaScript enabled

AsyncTask Source Code

 ·  ☕ 4 min read

AsyncTask类的初始化过程

初始化阶段:

  • 初始化线程池THREAD_POOL_EXECUTOR。用于执行任务。
  • 构造一个负责调度线程的线程池的Executor SerialExecutor,用于任务的排队,维护AsyncTask的任务串行执行。
  • 构造一个sHandlerInternalHandler。负责将执行结果从线程切换到主线程(UI线程)。
    AsyncTask内部的线程是通过一个线程池负责调度执行 :

构造THREAD_POOL_EXECUTOR

1
2
3
4
5
6
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
	CORE_POOL_SIZE,  //核心线程池大小,CPU核心数+1
	MAXIMUM_POOL_SIZE,  //线程池最大容量,CPU核心数*2+1
	KEEP_ALIVE,TimeUnit.SECONDS,  //每个空闲线程的等待时间,60秒
	sPoolWorkQueue, //缓冲队列为LinkedBlockingQueue
	sThreadFactory); //新建线程的工程方法,每个线程使用一个静态自增标志命名

AsyncTask的线程池不同于Java中通过Executors.newFixedThreadPool(int nThreads)创建的线程池。

Java的newFixedThreadPool

1
2
3
4
5
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

比较两者可知 :

  • FixedThreadPool的核心线程池容量和最大线程池容量相等。
  • FixedThreadPool的缓存队列为没有数量限制的LinkedBlockingQueue。
  • FixedThreadPool的空闲线程的等待时间为0,线程完成之后就会被回收。
  • AsyncTask的核心线程池容量和最大线程池容量都与当前设备的CPU核心数有关。
  • AsyncTask的缓存队列有最大容量限制。
  • AsyncTask的空闲线程会等待60s才被回收。

这样的差别就使得AsyncTask不适合做耗时线程的操作。如果一个线程太耗时,线程池又满了,那后面的线程就会一直等待。

线程池的配置参数

1
2
3
4
static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
static final int CORE_POOL_SIZE = CPU_COUNT + 1;
static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
static final int KEEP_ALIVE = 1;

线程池缓存队列为LinkedBlockingQueue

1
2
private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(128);

新建线程的工厂方法

1
2
3
4
5
6
7
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());
        }
    };

SerialExecutor

创建AsyncTask实例

AsyncTask实例主要拥有以下属性 :

  • WorkerRunnable<Params, Result> mWorker : 实现了Callable接口
  • FutureTask mFuture : 一个并发类,充当Runnable的作用。
  • volatile Status mStatus : 当前AsyncTask的状态 : PENDING,RUNNING,FINISHED
  • AtomicBoolean mCancelled : 任务是否被取消
  • AtomicBoolean mTaskInvoked : 任务是否执行

执行任务

时序图

Executor的execute方法 :

AsyncTask内部的SerialExecutor实现了Executor接口,提供了execute方法的实现

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);
        }
    }
}

首先把FutureTask对象插入到队列mTasks中,如果这个时候没有正在活动的AsyncTask任务,就会调用 scheduleNext() 来执行下一个任务。
同时,当mTask队列中的FutureTask对象执行完成之后,也会调用 scheduleNext() 来执行下一个任务。

这就证明AsyncTask是串行执行的,同一时刻只能有一个处于活动状态的任务。下一个必须等上一个执行完成之后,才能执行。

FutureTask对象执行任务是通过调用自己的run方法,在run方法中会调用 mWoker 的 call 方法。

mWorker = new WorkerRunnable<Params, Result>() {
    public Result call() throws Exception {
        mTaskInvoked.set(true);
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
        //noinspection unchecked
        return postResult(doInBackground(mParams));
    }
};

mWorker首先把mTaskInvoked设为 true 表示,当前任务已经被调用过了。然后执行 AsynckTask 的 doInBackground 方法,接着将返回值传递给 postResult 方法。

postResult的实现

1
2
3
4
5
6
7
private Result postResult(Result result) {
    @SuppressWarnings("unchecked")
    Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
            new AsyncTaskResult<Result>(this, result));
    message.sendToTarget();
    return result;
}

postResult 方法通过 sHandler 发送一个 MESSAGE_POST_RESULT 消息。

sHandler的实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
private static class InternalHandler extends Handler {
    @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;
        }
    }
}

sHandler 是一个静态对象的,在类加载时就被创建。为了能将消息从线程池传递到主线程,就要求AsyncTask类必须在主线程中加载,否则同一个进程中的AsyncTask无法正常工作。Android系统会在Application启动时调用AsyncTask的init方法。

sHandler 收到 MESSAGE_POST_RESULT 消息后会调用 AsyncTask 的 finish 方法。

finish方法

1
2
3
4
5
6
7
8
private void finish(Result result) {
    if (isCancelled()) {
        onCancelled(result);
    } else {
        onPostExecute(result);
    }
    mStatus = Status.FINISHED;
}

如果 AsyncTask 任务被取消了,就调用 onCancelled 方法,否则调用 onPostExecute 方法。

在Android 3.0 开始,AsyncTask 多加了一个线程池SerialExecutor来串行执行任务。

想让AsyncTask并行执行,可以调用executeOnExecutor(Executor exec, Params... params)传入自己的线程池。也可以直接使用AsyncTask的线程池。

例如

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    new MyAsyncTask("Task1").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");
    new MyAsyncTask("Task2").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");
    new MyAsyncTask("Task3").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");
}
class MyAsyncTask extends AsyncTask<String, Integer, String> {
    private String name;
    public MyAsyncTask(String name) {
        this.name = name;
    }
    @Override
    protected String doInBackground(String... params) {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return name;
    }
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        Log.i("TAG", s);
    }
}
Support the author with
alipay QR Code
wechat QR Code

Yang
WRITTEN BY
Yang
Developer