zoukankan      html  css  js  c++  java
  • BdAsyncTask学习

    综述

    是什么

    BdAsyncTask是仿照系统的AsyncTask重写的异步处理任务。用法和系统原生的AsyncTask一样,复写doInBackground、onPreExecute、onPostExecute、onProgressUpdate等方法

    为什么

    既然系统已经提供了AsyncTask,我们为何要重写一份BdAsyncTask那?

    AsyncTask的缺陷

    • 不同的Android版本AsyncTask的实现不同。AsyncTask是1.5版本引入的,当时的是实现是AsyncTask串行的运行在一个后台运行的线程中;1.6改为线程池,允许多个AsyncTask并行执行;从3.0开始为了避免并行执行的一些问题,又改为再一个后台线程中国年执行了。
    • 没有优先级控制。在一个app中,根据任务的紧急程度,需要有优先级控制。
    • 没有并行度控制。有上下文关系的任务可能需要串行;没有上下文关系的任务可以考虑使用并行,提高效率。

    基于以上的原因,我们需要提供一个不依赖系统版本的AsyncTask,并且支持优先级控制,支持并行度控制。

    名词解释

    优先级

    • SUPER_HIGH:线程优先级设置为Process.THREAD_PRIORITY_DEFAULT - 2
    • HIGH:线程优先级设置为Process.THREAD_PRIORITY_DEFAULT - 1
    • MIDDLE:线程优先级设置为Process.THREAD_PRIORITY_DEFAULT
    • LOW:线程优先级设置为Process.THREAD_PRIORITY_BACKGROUND

    优先级表示任务的重要程度,图片加载的优先级一般问LOW,网络访问的优先级一般为SUPER_HIGH。

    并行度

    • SERIAL, // 串行
    • TWO_PARALLEL, // 两个任务并行
    • THREE_PARALLEL, // 三个任务并行
    • FOUR_PARALLEL, // 四个任务并行
    • CUSTOM_PARALLEL, // 自定义个数,需要配置num参数,如果不配置,为串行
    • MAX_PARALLEL;// 多个任务并行

    并行度表示任务和任务之间的关系。比如贴吧IM异步任务就是SERIAL的,保证解析、存库等是串行执行的,不会出现数据错乱。

    实现

    BdAsyncTaskExecutor中定义了线程池,核心线程数7个,最大线程数256个。
    维护了三个队列:waiting、Running、timeout。
    图片

    执行流程

    1. 执行BdAsyncTask的execute方法,如果是isSelfExecute则直接new 一个新的Thread执行;否则按照优先级加入到waiting队列中。
    2. 调度:从waiting队头开始遍历
      • 如果任务优先级是SUPER_HIGH,并且没有设置并行度,则立即执行
    • 如果任务优先级是HIGH,则判断Running队列中,若正在运行的高、中、低>=核心线程数,则直接返回;否则走步骤3
    • 如果任务优先级是MIDDLE,则判断Running队列中,若正在运行的高、中、低>=核心线程数-1,则直接返回。减去1保证有HIGH任务可以尽快执行;否则走步骤3
    • 如果任务优先级是LOW,则判断Running队列中,若正在运行的高、中、低>=核心线程数-2,则直接返回。减去2是为了保证有HIGH和MIDDLE任务可以尽快执行;否则走步骤3
    1. 通过2判断,保证了核心线程池中,还有空余线程供该任务使用。但是这并不能保证该任务一定可以执行,需要判断该任务的并行度
      • 该任务的并行度为SERIAL,如果Running队列中已经有和该任务并行度相同的任务在执行,则继续向后遍历waiting队列;否则走步骤4
      • 该任务的并行度为TWO_PARALLEL,如果Running队列中和该任务拥有相同并行度的任务数>=2,继续向后遍历waiting队列;否则走步骤4
      • 其他并行度以此类推
    2. 通过3,可以获取到真正可以执行的任务,调用BdAsyncTask doinBackground 方法处理耗时操作,同时启动一个超时计时器
      在超时时间内,完成任务,则取消超时计时器,并开始下一次调度。如果任务超时,则将任务从Running队列进入timeout队列,并开始下一次调度。timeout队列大小超过总线程数-2*核心线程数后,最老的任务会被取消掉。

    栗子

    mParallel = new BdAsyncTaskParallel(BdAsyncTaskParallelType.SERIAL, BdUniqueId.gen());
    //在初始化方法中初始化,只初始化一次,之后使用该mParallel的任务之间就可以并行执行。
    //BdUniqueId.gen()保证了唯一性
    
    HTTPAsyncTask mTask = new HTTPAsyncTask(m, task);
    mTask.setTag(tag);
    mTask.setParallel(mParallel);
    mTask.setPriority(BdAsyncTaskPriority.SUPER_HIGH);
    mTask.execute();
    

    setTag:tag用于标识一类任务,可以通过BdAsyncTask.getTaskNum(tag),获取这个tag的任务数。

    setParallel:mParallel表示并行度,如上图中,如果多个HTTPAsyncTask同时执行execute后,则这些task之间是并行执行的,因为这些任务使用了同一个Parallel。类型是BdAsyncTaskParallel;并行度的构造方法:BdAsyncTaskParallel(BdAsyncTaskParallelType type, BdUniqueId tag),用tag来标识唯一标识这个并行度。

  • 相关阅读:
    第一篇随笔
    我的第一篇博客
    第一次博客
    芜湖
    芜湖~
    起飞
    第一天
    第一篇随笔
    第一篇随笔
    随笔
  • 原文地址:https://www.cnblogs.com/xitang/p/4930978.html
Copyright © 2011-2022 走看看