源码阅读-AsyncTask-任务调度

0. 相关资料

    源码地址
    android.os.AsyncTask
    java.util.concurrent.Executors

    参考文章
    Android实战技巧:深入解析AsyncTask
    ThreadPoolExecutor Java文档
    Executors Java文档
    java中关键字volatile的作用

1. AsyncTask#execute与AsyncTask#executeOnExecutor

    public static void execute(Runnable runnable)
    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params)

    AsyncTask#execute本质是调用THREAD_POOL_EXECUTOR,通过synchronized来保证线程池中的任务是一个一个调用的。
    AsyncTask#executeOnExecutor可以指定一个Execurtor来进行任务调度。

    AsyncTask拥有2个内置Executor,Executors拥有4个内置的Executor,这6个Executor都可以在AsyncTask#executeOnExecutor上面使用。一个Executor最多能执行多少个任务?这些Executor有什么区别?如何自定义一个Executor?这些问题是本文关注的重点。

2. ThreadPoolExecutor的构造

    上面说的六个Executor都是ThreadPoolExecutor,区别是构造对象的时候,使用的参数不同。下面说明ThreadPoolExecutor的构造函数。
    ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)

    ThreadPoolExecutor Java文档的描述如下:
    corePoolSize - 池中所保存的线程数,包括空闲线程。
    maximumPoolSize - 池中允许的最大线程数。
    keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
    unit - keepAliveTime 参数的时间单位。
    workQueue - 执行前用于保持任务的队列。此队列仅保持由 execute 方法提交的 Runnable 任务。

    另外文档中描述了corePoolSize与maximumPoolSize的关系:如果运行的线程多于 corePoolSize 而少于 maximumPoolSize,则仅当队列满时才创建新线程。

    我的理解是这样的:
    如果运行的任务数量小于corePoolSize ,那么新的任务会立即执行。
    如果任务数量大于了corePoolSize ,那么会放到workQueue中,如果workQueue满了,但是任务数量没有超过maximumPoolSize ,那么创建一个新线程来执行。
    如果workQueue满了,池中任务数量已经达到maximumPoolSize,那么会执行ThreadPoolExecutor的错误处理机制,默认是丢弃该任务。

3. AsyncTask内置Executor

    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
    public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
    SERIAL_EXECUTOR实际上调用THREAD_POOL_EXECUTOR,只是通过synchronized来保证线程池中的任务是一个一个调用的。AsyncTask#execute就是使用SERIAL_EXECUTOR,因此AsyncTask#execute在执行的时候是一个一个执行的。注意SERIAL_EXECUTOR 是静态的,所以无论在哪个线程中,使用AsyncTask#execute执行任务,任务都在一起执行。

    THREAD_POOL_EXECUTOR,corePoolSize=5,maximumPoolSize=128,keepAliveTime =1,keepAliveTime =秒,workQueue= LinkedBlockingQueue<Runnable>(10)
    可以有5个线程可以同时运行
    超过5个之后的线程会放到workQueue
    队列中最多放10个,超过之后,直接创建新的线程直接执行
    最多一共能放128个线程,超过128个之后的线程会被丢弃

4. Executors的内置Executor

    Executors#newCachedThreadPool()

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
    SynchronousQueue是不存储元素的阻塞队列。由于corePoolSize=0,每次新来一个任务,都会放到workQueue中,但是SynchronousQueue是不存储元素的,所以会立即开启线程执行。由于maximumPoolSize=Integer.MAX_VALUE,执行的线程数量是没有上限的。文档中说, 对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。

    Executors#newFixedThreadPool()

  public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
  }

    池中最多可以同时运行nThreads个线程,多余的任务都放在workQueue中,workQueue没有上限,可以存储任意多个任务。

    Executors#newSingleThreadExecutor()

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    池中只能运行一个线程,其他任务都放在workQueue中。相当于Executors#newFixedThreadPool(1)。

    Executors#newSingleThreadScheduledExecutor

    public static ScheduledExecutorService newSingleThreadScheduledExecutor()

    创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。


     这里主要关注两个Executor,Executors#newCachedThreadPool()和Executors#newFixedThreadPool()。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值