美文网首页
AsyncTask源码解读的几点心得

AsyncTask源码解读的几点心得

作者: 蓝灰_q | 来源:发表于2017-11-26 23:17 被阅读122次

    需求
    我们知道,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,这样也不可能重复执行任务了。

    相关文章

      网友评论

          本文标题:AsyncTask源码解读的几点心得

          本文链接:https://www.haomeiwen.com/subject/ftolbxtx.html