(源码来自sdk7.0)
构造方法
构造方法有3个
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
this((Looper) null);
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide
*/
public AsyncTask(@Nullable Handler handler) {
this(handler != null ? handler.getLooper() : null);
}
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide
*/
public AsyncTask(@Nullable Looper callbackLooper) {
第3个构造是主要构造,但被隐藏了。应用层常用到的是无参构造即传入一个null至该构造,实际等价于传入MainLooper。
/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*
* @hide
*/
public AsyncTask(@Nullable Looper callbackLooper) {
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
但是这里的主线程looper和非主线程looper实际上是分开处理的,非主线程需要自己处理不同message的结果的分发,而主线程的源码中完全替你封装好了。
主线程的mHandler初始化getMainHandler
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
这个InternalHandler就是做了MESSAGE_POST_RESULT和MESSAGE_POST_PROGRESS的主线程回调
因为静态内部类在假泛型中无法获取到泛型类型,而暴露给API的
protected void onProgressUpdate(Progress... values)
protected void onPostExecute(Result result)
显然希望使用到泛型约束。这里不得已用了unchecked屏蔽编译错误。因为每个AsyncTask的只能执行一次,这里的类型安全是没问题的~~~ 就是代码可读性稍差,
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@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]); //主线程调用被复写的onCancel或者onPostExecute
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData); //主线程调用被复写的onProgressUpdate
break;
}
}
}
构造方法中除了创建了handler,更重要的是初始化了FutureTask
mWorker = new WorkerRunnable<Params, Result>() { //WorkRunnable其实就是个Callback的实现,静态内部类存放Params规避内存泄漏
public Result call() throws Exception {
mTaskInvoked.set(true); //mTaskInvoked在call第一行用于标识任务已经被执行。在done中调用postResultIfNotInvoked提取判断
//因为done()函数如果在future的cancel时是由调用线程执行的 可能存在线程安全问题
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams); //子线程执行执行复写的doInBackground任务
Binder.flushPendingCommands(); //以下是该静态函数的api注释
/*将当前线程中挂起的所有Binder命令都刷新到内核驱动。
这可以在执行可能阻塞很长时间的操作之前调用,
以确保任何挂起的对象引用已经被释放。
这样可以防止这一耗时过程的持续时间超过对象应有的生命周期。*/
} catch (Throwable tr) {
mCancelled.set(true); //这里也是一个AtomicBoolean 标识cancel
throw tr;
} finally {
postResult(result);//mTaskInvoked被设置为true这句代码执行之后,就保证了final中调用postResult
}
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());//future阻塞get()获取result 并根据抛出的异常处理状态
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
}
这里有个小疑问,mTaskInvoked是一个AtomicBoolean,保证多线程的原子性,但是这里并没有调用compareAndSet方法,那么使用原子类的意义在哪里呢? 这里在我的理解里 应该只需要声明volatile boolean mTaskInvoked就可以了,如有高见欢迎讨论。
postResultIfNotInvoked函数的意义,当future没有执行就被cancel后,cancel调用done()函数,获得到get()将是一个空,这时进入!wasTaskInvoked流程 postResult(null)
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}
线程调度
异步任务启动的入口
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) { //这段代码保证AsyncTask只能被执行一次
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute(); //主线程回调执行一次
mWorker.mParams = params; //配置参数给Callback
exec.execute(mFuture); //全局调度执行器 接管futrue
return this;
}
不管我们通常调用的execute(Params... params)还是提供给我们直接运行一个runnable的
@MainThread
public static void execute(Runnable runnable) {
sDefaultExecutor.execute(runnable);
}
实际都是使用全局调度执行器sDefaultExecutor进行处理,它的默认实现是一个串行的分发
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
在主线程调用
并且他的实现保证了串行:全局中多个AsyncTask被execute,只会有deque头部那个成为mActive,依序执行
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() { //offer插入ruunable到deque的尾部
//代理包装了r 实际执行是由线程池做的 这里只是添加了 调度工作的代理层
public void run() {
try { //这样try catch 不阻碍异常的抛出 同时又能保证 一个runnable执行完之后 一定执行下一个
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) { //塞进队列后检查:如果现在没有执行的runnable 那么开始干活了
scheduleNext();
}
}
protected synchronized void scheduleNext() { //这个函数执行时机在1、deque从空到有时 与2、sWorkExecutor有runnable执行完毕时调用
if ((mActive = mTasks.poll()) != null) { //头部取出 开始执行
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
线程池
我们看到了真正消费mTasks中的Runnable的是THREAD_POOL_EXECUTOR.execute(mActive)
他是一个全局的executor
public static final Executor THREAD_POOL_EXECUTOR;
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
他也是public的 可以直接设置。缺省值为一个核心线程cpu-1、最大线程2倍cpu、非核心线程待活时间10秒、等待工作队列长度128的线程池
超出工作队列的拒绝策略用的是java缺省的抛异常RejectedExecutionException
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
可以关注一下线程工厂的计数器 用的是原子类AtomicInt的自增
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());
}
};