源码解析Android中AsyncTask的工作原理
在之前的博客《Android中AsyncTask使用详解》中我们提到AsyncTask是对Thread和Handler的组合包装,本文将通过解析的方式让大家了解AsyncTask的工作原理。
AsyncTask的源码链接https://github.com/android/platform_frameworks_base/blob/master/core/java/android/os/AsyncTask.java
AsyncTask一开始定义了一些字段,如下所示:
private static final String LOG_TAG = "AsyncTask";
//CPU_COUNT为手机中的CPU核数
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
//将手机中的CPU核数加1作为AsyncTask所使用的线程池的核心线程数的大小
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
//将CPU_COUNT * 2 + 1作为AsyncTask所使用的线程池的最大线程数的大小
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE = 1;
//实例化线程工厂ThreadFactory,sThreadFactory用于在后面创建线程池
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
//mCount为AtomicInteger类型,AtomicInteger是一个提供原子操作的Integer类,
//确保了其getAndIncrement方法是线程安全的
private final AtomicInteger mCount = new AtomicInteger(1);
//重写newThread方法的目的是为了将新增线程的名字以"AsyncTask #"标识
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
//实例化阻塞式队列BlockingQueue,队列中存放Runnable,容量为128
private static final BlockingQueue sPoolWorkQueue =
new LinkedBlockingQueue(128);
//根据上面定义的参数实例化线程池
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
通过以上代码和注释我们可以知道,AsyncTask初始化了一些参数,并用这些参数实例化了一个线程池THREAD_POOL_EXECUTOR
,需要注意的是该线程池被定义为public static final
,由此我们可以看出AsyncTask内部维护了一个静态的线程池,默认情况下,AsyncTask的实际工作就是通过该THREAD_POOL_EXECUTOR
完成的。
我们继续,在执行完上面的代码后,AsyncTask又有如下一条语句:
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
上面的代码实例化了一个SerialExecutor类型的实例SERIAL_EXECUTOR
,它也是public static final
的。SerialExecutor是AsyncTask的一个内部类,代码如下所示:
//SerialExecutor实现了Executor接口中的execute方法,该类用于串行执行任务,
//即一个接一个地执行任务,而不是并行执行任务
private static class SerialExecutor implements Executor {
//mTasks是一个维护Runnable的双端队列,ArrayDeque没有容量限制,其容量可自增长
final ArrayDeque mTasks = new ArrayDeque();
//mActive表示当前正在执行的任务Runnable
Runnable mActive;
public synchronized void execute(final Runnable r) {
//execute方法会传入一个Runnable类型的变量r
//然后我们会实例化一个Runnable类型的匿名内部类以对r进行封装,
//通过队列的offer方法将封装后的Runnable添加到队尾
mTasks.offer(new Runnable() {
public void run() {
try {
//执行r的run方法,开始执行任务
//此处r的run方法是在线程池中执行的
r.run();
} finally {
//当任务执行完毕的时候,通过调用scheduleNext方法执行下一个Runnable任务
scheduleNext();
}
}
});
//只有当前没有执行任何任务时,才会立即执行scheduleNext方法
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
//通过mTasks的poll方法进行出队操作,删除并返回队头的Runnable,
//将返回的Runnable赋值给mActive,
//如果不为空,那么就让将其作为参数传递给THREAD_POOL_EXECUTOR的execute方法进行执行
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
通过以上代码和注释我们可以知道:
SerialExecutor实现了Executor接口中的execute方法,该类用于串行执行任务,即一个接一个地执行任务,而不是并行执行任务。
SerialExecutor内部维护了一个存放Runnable的双端队列mTasks。当执行SerialExecutor的execute方法时,会传入一个Runnable变量r,但是mTasks并不直接存储r,而是又新new了一个匿名Runnable对象,其内部会调用r,这样就对r进行了封装,将该封装后的Runnable对象通过队列的offer方法入队,添加到mTasks的队尾。
SerialExecutor内部通过mActive存储着当前正在执行的任务Runnable。当执行SerialExecutor的execute方法时,首先会向mTasks的队尾添加进一个Runnable。然后判断如果mActive为null,即当前没有任务Runnable正在运行,那么就会执行scheduleNext()方法。当执行scheduleNext方法的时候,会首先从mTasks中通过poll方法出队,删除并返回队头的Runnable,将返回的Runnable赋值给mActive,如果不为空,那么就让将其作为参数传递给THREAD_POOL_EXECUTOR的execute方法进行执行。由此,我们可以看出SerialExecutor实际上是通过之前定义的线程池THREAD_POOL_EXECUTOR
进行实际的处理的。
当将mTasks中的Runnable作为参数传递给THREAD_POOL_EXECUTOR执行execute方法时,会在线程池的工作线程中执行匿名内部类Runnable中的try-finally代码段,即先在工作线程中执行r.run()方法去执行任务,无论任务r正常完成还是抛出异常,都会在finally中执行scheduleNext方法,用于执行mTasks中的下一个任务。从而在此处我们可以看出SerialExecutor是一个接一个执行任务,是串行执行任务,而不是并行执行。
AsyncTask内部定义了一个Status枚举类型,如下所示:
public enum Status {
//PENDING表示还没有开始执行任务
PENDING,
//RUNNING表示已经开始执行任务
RUNNING,
//FINISHED表示任务已经执行完成或被取消了,总之onPostExecute方法已经被调用了
FINISHED,
}
一个AsyncTask正常情况下会经历PENDING->RUNNING->FINISHED三个状态。
AsyncTask还定义了以下字段:
//用于通过Handler发布result的Message Code
private static final int MESSAGE_POST_RESULT = 0x1;
//用于通过Handler发布progress的Message Code
private static final int MESSAGE_POST_PROGRESS = 0x2;
//sDefaultExecutor表示AsyncTask默认使用SERIAL_EXECUTOR作为Executor,
//即默认情况下AsyncTask是串行执行任务,而不是并行执行任务
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
//InternalHandler是AsyncTask中定义的一个静态内部类,其绑定了主线程的Looper和消息队列
private static InternalHandler sHandler;
//mWorker是一个实现了Callable接口的对象,其实现了Callable接口的call方法
private final WorkerRunnable mWorker;
//根据mFuture是一个FutureTask对象,需要用mWorker作为参数实例化mFuture
private final FutureTask mFuture;
//AsyncTask的初始状态位PENDING
private volatile Status mStatus = Status.PENDING;
//mCancelled标识当前任务是否被取消了
private final AtomicBoolean mCancelled = new AtomicBoolean();
//mTaskInvoked标识当前任务是否真正开始执行了
private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
我们对以上代码再进行一下说明:
sDefaultExecutor表示AsyncTask执行任务时默认所使用的线程池,sDefaultExecutor的初始值为SERIAL_EXECUTOR,表示默认情况下AsyncTask是串行执行任务,而不是并行执行任务。
InternalHandler是AsyncTask中定义的一个静态内部类,其部分源码如下所示:
private static class InternalHandler extends Handler {
public InternalHandler() {
//Looper类的getMainLooper方法是个静态方法,该方法返回主线程的L