AsyncTask源码解读的几点心得

需求
我们知道,AsyncTask其实是Google给出的轻量级异步方案,它要实现的核心在于:
轻量,不可重复执行。
串行,默认只能一个接一个执行。
回调,处理完任务后通知回主线程。
特性
AsyncTask把Handler和线程池结合起来,提供轻量级异步处理,每个AsyncTask实例只能执行一次,默认是串行执行,但是可以设置为并行处理。

线程池
AsyncTask不使用固定参数的线程池,而是根据处理器确定线程池的核心线程和可用线程数,队列还是128的BlockingQueue。
这个线程池是一个static final常量,所以也是App内全局使用一个线程池。

默认串行处理
默认是串行处理,因为默认的Executor是SerialExecutor,这是一个static final常量,所以App内全局使用同一个SerialExecutor,这就需要使用队列来生产和消费。
入列:SerialExecutor的execute函数中,会执行一个ArrayDeque队列的offer,经过一连串调用,实际执行的是该队列的addLast(E e)函数,也就是添加队列;
出列:执行队列的poll操作,交给AsyncTask的线程池操作。
所以,SerialExecutor在接收任务时,用一个默认长度16的ArrayDeque来入列,出列的Runnable统一交给线程池处理。
引用SerialExecutor后,所有默认的AsyncTask是串行的,一次只能执行一条runnable,如果想并行处理,需要我们用executeOnExecutor来输入一个线程池。
虽然是串行,但是不怕中间有出错,因为每个runnable的run外面都包了try finally,在finally里执行scheduleNext(),确保会连续执行后面的操作。

基本流程
1.创建AsyncTask时会创建一个callable的mWorker和一个runnable的mFuture,mWorker会被mFuture持有;
2.在执行AsyncTask时调用的execute,会调用executeOnExecutor,然后会走默认的SerialExecutor的execute函数,传进去执行的就是mFuture,这样就可以在done的时候做处理;
3.在SerialExecutor的execute函数里会先入队列,再出队列,包装为一个runnable的mActive,交给线程池去执行。
4.SerialExecutor会把所有的runnable赋给一个mActive对象,再把这个mActive交给线程池,因为mActive对象在整个App里只有一个,所以就用它来判断是不是有任务还在执行(是否为null),确保默认情况下不会并行处理。
5.在线程池中,mActive作为runnable先addWorker,再runWorker,在runWorker时,这个runnbale会被置为null,这样在SerialExecutor那里,mActive就是null值了,可以继续处理下一个任务。
6.判断mActive为null才能执行,是在调用execute时发生的,这样可以避免出现并行。
7.在有多个排队任务的情况下,SerialExecutor在try finally里执行scheduleNext(),所以每个任务run完成之后会顺序执行下一个任务。

AsyncTask不能执行多次
原因有两个,一个是有Status状态检查,一个是FutureTask会清除Worker
1.因为用一个Status设置了状态,默认为Pending,也只哟Pending才能执行,一旦进入Running和Finished,就不会再执行了(throw 异常),所以一个AsyncTask不能执行多次。
2.每个AsyncTask的mFuture和mWorker都是final的,mFuture执行完毕后,会把持有的callable,也就是mWorker清空为null,这样也不可能重复执行任务了。

附录;

主要针对做Android开发1到5年,需要系统深入的提升完善自己的技术体系的开发者朋友。

附录一;Android高级技术大纲

附录二;Android进阶实战技术视频

获取方式;

加Android进阶群;701740775。即可前往免费领取。麻烦备注一下csdn领取资料

猜你喜欢

转载自blog.csdn.net/feiyu1947/article/details/86597030