文章目录

  • 一、AsyncTask 异步任务执行方法 execute() 引入
  • 二、AsyncTask 异步任务执行方法 execute()
  • 三、sDefaultExecutor 线程池解析
  • 四、executeOnExecutor 方法解析
  • 五、AsyncTask 异步任务执行方法 execute() 相关源码注释

一、AsyncTask 异步任务执行方法 execute() 引入


上一篇博客中 【Android 异步操作】AsyncTask 异步任务 ( 参数简介 | 方法简介 | 使用方法 | AsyncTask 源码分析 ) , 讲解了 AsyncTask<Params, Progress, Result> 异步任务的构造函数 ;

异步任务执行有两个方法 :

  • 构造异步任务 : 调用 AsyncTask 的构造函数 , 创建 AsyncTask 异步任务对象 ;
  • 执行异步任务 : 调用 AsyncTask 异步任务对象的 execute() 方法 , 执行异步任务 ;

本篇博客中讲解执行函数 AsyncTask<Params, Progress, Result> execute(Params… params) ;

// 1. 创建 AsyncTask 异步任务
MyAsyncTask mMyAsyncTask = new MyAsyncTask();// 2. 执行 AsyncTask 异步任务
mMyAsyncTask.execute();

二、AsyncTask 异步任务执行方法 execute()


AsyncTask<Params, Progress, Result> execute(Params… params) 方法作用 : AsyncTask 异步任务的 execute() 函数作用就是提交任务 , 其提交的任务就是 FutureTask , 其使用的是 线程池 提交任务 ;

① 参数 : 使用指定的参数 , 执行任务 ;

② 返回值 : 这个任务返回 AsyncTask<Params, Progress, Result> 本身对象 , 以便调用者可以持有该异步任务的引用 ;

③ 任务调度 : 该方法在队列上调度一个任务 , 该任务在一个单独的后台线程 , 或线程池中执行 ; 第一次引入后 , 异步任务在单独后台线程中被串行执行 ;

④ 不同版本的执行任务载体 :

  • Android 1.6(API 级别 4)及以下的版本是在一个后台线程中串行执行 ;
  • Android 2.0(API 级别 5)及以上的版本是在线程池中串行执行 ;
  • Android 3.0(API 级别 11)及以上的版本有回复到在一个后台线程中串行执行 ;

在该类中 , 最终调用了 executeOnExecutor() 方法 , 使用 sDefaultExecutor 默认串行线程池执行任务 ;

public abstract class AsyncTask<Params, Progress, Result> {@MainThreadpublic final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);}
}

如果同时调用 AsyncTask 异步任务的 execute() 函数执行任务 , 其任务会逐个串行执行 , 不是并行的 ;

AsyncTask<Params, Progress, Result> 对象的 execute() 执行的任务是有序的 ;

三、sDefaultExecutor 线程池解析


上述执行异步任务的方法 executeOnExecutor() , 传入了 sDefaultExecutor 线程池作为参数 , 本节分析 sDefaultExecutor 线程池 ;

sDefaultExecutor 是成员变量 , 其声明类型是 Executor , 实际类型是自定义的线程池 SerialExecutor() ;

SerialExecutor 是一个线程池 , 执行任务 , 每次只执行一个任务 , 按照串行顺序执行 ; 该序列对于特定进程来说是全局的 , 即一个进程只有一个该序列 ;

在该线程池中 , 维护了如下两个成员 :

  • 任务队列 ArrayDeque mTasks
  • 当前执行任务 Runnable mActive

该线程池中 void execute(final Runnable r) 执行任务方法 :

  • 执行当前传入的任务 : 自己创建一个 Runnable , 在其 run() 方法中执行传入的参数的 r 的 run() 方法 ;
  • 执行下一个任务 : 执行完毕当前任务后 , 调用 scheduleNext() 执行下一个任务

scheduleNext() 方法 用于执行下一个任务 , 从队列中取出一个任务 , 如果取出的任务不为空 , 那么就执行该任务 ; 调用 SerialExecutor 类的 execute(final Runnable r) 方法执行该任务 ;

public abstract class AsyncTask<Params, Progress, Result> {private static final String LOG_TAG = "AsyncTask";/*** 自定义线程池 ; * 一个线程池 , 执行任务 , 每次只执行一个任务 , 按照串行顺序执行 ; * 该序列对于特定进程来说是全局的 , 即一个进程只有一个该序列 ; */public static final Executor SERIAL_EXECUTOR = new SerialExecutor();@UnsupportedAppUsageprivate static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;/*** 自定义线程池 ; * 一个线程池 , 执行任务 , 每次只执行一个任务 , 按照串行顺序执行 ; * 该序列对于特定进程来说是全局的 , 即一个进程只有一个该序列 ; */private static class SerialExecutor implements Executor {// 任务队列 final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();// 当前执行的任务 Runnable mActive;// 执行任务public synchronized void execute(final Runnable r) {// 自己创建一个 Runnable , 在其 run() 方法中执行如下方法 : // 传入的 execute(final Runnable r) 方法参数的 r 的 run() 方法 ; mTasks.offer(new Runnable() {public void run() {try {r.run();} finally {// 执行完毕当前任务后 , 执行下一个任务scheduleNext();}}});// 如果当前任务为空 , 那么执行下一个任务 if (mActive == null) {scheduleNext();}}/*** 执行下一个任务 * 从队列中取出一个任务 , 如果取出的任务不为空 , 那么就执行该任务 ; * 调用 SerialExecutor 类的 execute(final Runnable r) 方法执行该任务 ; */protected synchronized void scheduleNext() {if ((mActive = mTasks.poll()) != null) {// 执行队列中的任务的操作 THREAD_POOL_EXECUTOR.execute(mActive);}}}
}

四、executeOnExecutor 方法解析


executeOnExecutor 方法是异步任务执行的核心方法 ;

执行流程如下 :

① 判定合法性 : AsyncTask 异步任务只能执行一次 , 必须确保该 AsyncTask 异步任务没有执行过 , 如果执行过直接抛出异常 ;

② 设置运行状态 : 将该异步任务状态设置成 Status.RUNNING 状态 , 防止第二次被执行 ;

③ 主线程初始化 : 执行 onPreExecute() 方法 , 用户可以在该方法中初始化 UI , 该操作在 UI 主线程中运行 ;

④ 子线程后台任务执行 : 执行 FutureTask 中的 Callable 任务 , 也就是异步任务 , 该操作在子线程中运行 ;

public abstract class AsyncTask<Params, Progress, Result> {    /*** 使用指定的参数 , 执行任务 ; * 这个任务返回 AsyncTask<Params, Progress, Result> 本身对象 , * 一遍调用者可以持有该异步任务的引用 ; * * 该方法通常与 THREAD_POOL_EXECUTOR 一同使用 , 允许多个任务在一个线程池中串行执行 , * 该线程池由 AsyncTask 异步任务管理 , 也可以使用自己的线程池定制相关行为 ; */@MainThreadpublic final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {// 首先判定当前状态是否合法 , 确保该 AsyncTask 异步任务没有执行过 , // 每个 AsyncTask 异步任务创建后只能执行一次 ; if (mStatus != Status.PENDING) {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;// 执行 doInBackground() 之前执行的方法 onPreExecute();// 设置 WorkerRunnable 的 Params[] mParams 参数mWorker.mParams = params;// 执行 FutureTask 中的 Callable 任务exec.execute(mFuture);return this;}}

五、AsyncTask 异步任务执行方法 execute() 相关源码注释


public abstract class AsyncTask<Params, Progress, Result> {private static final String LOG_TAG = "AsyncTask";/*** 自定义线程池 ; * 一个线程池 , 执行任务 , 每次只执行一个任务 , 按照串行顺序执行 ; * 该序列对于特定进程来说是全局的 , 即一个进程只有一个该序列 ; */public static final Executor SERIAL_EXECUTOR = new SerialExecutor();@UnsupportedAppUsageprivate static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;/*** 自定义线程池 ; * 一个线程池 , 执行任务 , 每次只执行一个任务 , 按照串行顺序执行 ; * 该序列对于特定进程来说是全局的 , 即一个进程只有一个该序列 ; */private static class SerialExecutor implements Executor {// 任务队列 final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();// 当前执行的任务 Runnable mActive;// 执行任务public synchronized void execute(final Runnable r) {// 自己创建一个 Runnable , 在其 run() 方法中执行如下方法 : // 传入的 execute(final Runnable r) 方法参数的 r 的 run() 方法 ; mTasks.offer(new Runnable() {public void run() {try {r.run();} finally {// 执行完毕当前任务后 , 执行下一个任务scheduleNext();}}});// 如果当前任务为空 , 那么执行下一个任务 if (mActive == null) {scheduleNext();}}/*** 执行下一个任务 * 从队列中取出一个任务 , 如果取出的任务不为空 , 那么就执行该任务 ; * 调用 SerialExecutor 类的 execute(final Runnable r) 方法执行该任务 ; */protected synchronized void scheduleNext() {if ((mActive = mTasks.poll()) != null) {// 执行队列中的任务的操作 THREAD_POOL_EXECUTOR.execute(mActive);}}}/*** 使用指定的参数 , 执行任务 ; * 这个任务返回 AsyncTask<Params, Progress, Result> 本身对象 , * 一遍调用者可以持有该异步任务的引用 ; * * 该方法在队列上调度一个任务 , 该任务在一个单独的后台线程  , 或线程池中执行 ; * 第一次引入后 , 异步任务在单独后台线程中被串行执行 ; * Android 1.6(API 级别 4)及以下的版本是在一个后台线程中串行执行 ; * Android 2.0(API 级别 5)及以上的版本是在线程池中串行执行 ; * Android 3.0(API 级别 11)及以上的版本有回复到在一个后台线程中串行执行 ; ** <p>改方法必须在 UI 线程中调用 ** @param 要执行的任务的参数.** @return 返回异步任务 AsyncTask 本身 .*/@MainThreadpublic final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);}/*** 使用指定的参数 , 执行任务 ; * 这个任务返回 AsyncTask<Params, Progress, Result> 本身对象 , * 一遍调用者可以持有该异步任务的引用 ; * * 该方法通常与 THREAD_POOL_EXECUTOR 一同使用 , 允许多个任务在一个线程池中串行执行 , * 该线程池由 AsyncTask 异步任务管理 , 也可以使用自己的线程池定制相关行为 ; */@MainThreadpublic final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {// 首先判定当前状态是否合法 , 确保该 AsyncTask 异步任务没有执行过 , // 每个 AsyncTask 异步任务创建后只能执行一次 ; if (mStatus != Status.PENDING) {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;// 执行 doInBackground() 之前执行的方法 onPreExecute();// 设置 WorkerRunnable 的 Params[] mParams 参数mWorker.mParams = params;// 执行 FutureTask 中的 Callable 任务exec.execute(mFuture);return this;}}

【Android 异步操作】AsyncTask 异步任务 ( AsyncTask 异步任务执行方法 execute 方法相关源码解析 )相关推荐

  1. Android 异步消息处理机制(Handler 、 Looper 、MessageQueue)源码解析

    1.Handler的由来 当程序第一次启动的时候,Android会同时启动一条主线程( Main Thread)来负责处理与UI相关的事件,我们叫做UI线程. Android的UI操作并不是线程安全的 ...

  2. 【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 一 | Activity 进程相关源码 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  3. Android之AsyncTask源码解析

    转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! ##前言 AsyncTask是一种轻量级的异步任务类,内部封装了Thread和Ha ...

  4. AsyncTask、HandlerThread、IntentSerivce源码解析

    在进行耗时操作时,一般new Thread().start();开启一个子线程,然后通过handler消息去更新ui(关于handler可以看这里:android Handler.Looper.Mes ...

  5. AsyncTask源码解析,你需要摸清的细节

    AsyncTask简介 1. AsyncTask提供了一种恰当的简单的跟UI Thread交互的方式. 2. 它不需要通过操控Threads或Handler就可以将后台操作以及其结果展示在UI Thr ...

  6. Redux异步解决方案之Redux-Thunk原理及源码解析

    前段时间,我们写了一篇Redux源码分析的文章,也分析了跟React连接的库React-Redux的源码实现.但是在Redux的生态中还有一个很重要的部分没有涉及到,那就是Redux的异步解决方案.本 ...

  7. 【Android 异步操作】线程池 ( 线程池作用 | 线程池种类 | 线程池工作机制 | 线程池任务调度源码解析 )

    文章目录 一.线程池作用 二.线程池种类 三.线程池工作机制 四.线程池任务调度源码解析 一.线程池作用 线程池作用 : ① 避免创建线程 : 避免每次使用线程时 , 都需要 创建线程对象 ; ② 统 ...

  8. Spring5源码 - 12 Spring事件监听机制_异步事件监听应用及源码解析

    文章目录 Pre 实现原理 应用 配置类 Event事件 事件监听 EventListener 发布事件 publishEvent 源码解析 (反推) Spring默认的事件广播器 SimpleApp ...

  9. Android多线程之IntentService源码解析

    想要了解 IntentService 的工作原理需要先对 Android 系统中以 Handler.Looper.MessageQueue 组成的异步消息处理机制以及 HandlerThread 有所 ...

最新文章

  1. Android开发将List转化为JsonArray和JsonObject
  2. Node.js权威指南 (7) - 实现基于TCP与UDP的数据通信
  3. Centos7编译安装nginx并设置反向代理
  4. 第三次学JAVA再学不好就吃翔(part73)--SimpleDateFormat类
  5. Tomcat 服务自动启动
  6. bzoj4171: Rhl的游戏
  7. C++基础:第七章 函数
  8. WPF中的Application类。
  9. scala下载新的版本号
  10. 三维虚拟工厂仿真交互展示有哪些功能
  11. 关于修复msvcp110.dll丢失的问题
  12. 统计学基础--假设检验
  13. NFormer: robust person re-identification with neighbor transformer
  14. bazel 链接第三方动态库_谷歌携手OPPO共同开发CameraX技术,第三方拍照应用有福了...
  15. easypoi.excel 导入不固定的合并单元格数据
  16. 【ORB-SLAM】原理部分
  17. cad旋转命令_如何将CAD图形旋转至水平位置?
  18. Tian Ji -- The Horse Racing 贪心算法
  19. python怎么编辑程序_少儿编程:Python系列24——字符串的替换和检索
  20. 安装安卓(Android)x86系统

热门文章

  1. Kubernetes-基于k8s-v1.14.2安装dashboard-1.10.1
  2. 站立会议报告(12)
  3. 卡拉OK效果的实现-iOS音乐播放器
  4. jQuery 分类导航菜单条点击变色
  5. [JAVA_开课吧资源]第一周 Java语言概述、Java语言基础
  6. 运用家居收纳储物空间 小空间变出大身材
  7. 判断、转载-【Cocos2D-X 】初窥门径(8)判断精灵点击-by小雨
  8. Python运维开发基础01-语法基础【转】
  9. Hadoop安装的ssh免密码登录步骤
  10. 设计模式6——创建型模式之原型模式