AsyncTask类的初始化过程
初始化阶段:
- 初始化线程池
THREAD_POOL_EXECUTOR
。用于执行任务。 - 构造一个负责调度线程的线程池的Executor
SerialExecutor
,用于任务的排队,维护AsyncTask的任务串行执行。 - 构造一个sHandler
InternalHandler
。负责将执行结果从线程切换到主线程(UI线程)。
AsyncTask内部的线程是通过一个线程池负责调度执行 :
构造THREAD_POOL_EXECUTOR
1 | public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor( |
AsyncTask的线程池不同于Java中通过
Executors.newFixedThreadPool(int nThreads)
创建的线程池。
Java的newFixedThreadPool
1 | public static ExecutorService newFixedThreadPool(int nThreads) { |
比较两者可知 :
- FixedThreadPool的核心线程池容量和最大线程池容量相等。
- FixedThreadPool的缓存队列为没有数量限制的LinkedBlockingQueue。
- FixedThreadPool的空闲线程的等待时间为0,线程完成之后就会被回收。
- AsyncTask的核心线程池容量和最大线程池容量都与当前设备的CPU核心数有关。
- AsyncTask的缓存队列有最大容量限制。
- AsyncTask的空闲线程会等待60s才被回收。
这样的差别就使得AsyncTask不适合做耗时线程的操作。如果一个线程太耗时,线程池又满了,那后面的线程就会一直等待。
线程池的配置参数
1 | static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); |
线程池缓存队列为LinkedBlockingQueue
1 | private static final BlockingQueue<Runnable> sPoolWorkQueue = |
新建线程的工厂方法
1 | private static final ThreadFactory sThreadFactory = new ThreadFactory() { |
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方法的实现
1 | private static class SerialExecutor implements Executor { |
首先把FutureTask对象插入到队列mTasks中,如果这个时候没有正在活动的AsyncTask任务,就会调用 scheduleNext() 来执行下一个任务。
同时,当mTask队列中的FutureTask对象执行完成之后,也会调用 scheduleNext() 来执行下一个任务。
这就证明AsyncTask是串行执行的,同一时刻只能有一个处于活动状态的任务。下一个必须等上一个执行完成之后,才能执行。
FutureTask对象执行任务是通过调用自己的run
方法,在run
方法中会调用 mWoker 的 call 方法。
1 | mWorker = new WorkerRunnable<Params, Result>() { |
mWorker首先把mTaskInvoked设为 true 表示,当前任务已经被调用过了。然后执行 AsynckTask 的 doInBackground 方法,接着将返回值传递给 postResult 方法。
postResult的实现
1 | private Result postResult(Result result) { |
postResult 方法通过 sHandler 发送一个 MESSAGE_POST_RESULT 消息。
sHandler的实现
1 | private static class InternalHandler extends Handler { |
sHandler 是一个静态对象的,在类加载时就被创建。为了能将消息从线程池传递到主线程,就要求AsyncTask类必须在主线程中加载,否则同一个进程中的AsyncTask无法正常工作。Android系统会在Application启动时调用AsyncTask的init方法。
sHandler 收到 MESSAGE_POST_RESULT 消息后会调用 AsyncTask 的 finish 方法。
finish方法
1 | private void finish(Result result) { |
如果 AsyncTask 任务被取消了,就调用 onCancelled 方法,否则调用 onPostExecute 方法。
在Android 3.0 开始,AsyncTask 多加了一个线程池SerialExecutor来串行执行任务。
想让AsyncTask并行执行,可以调用executeOnExecutor(Executor exec, Params... params)
传入自己的线程池。也可以直接使用AsyncTask的线程池。
例如
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!