当前位置: 首页 > news >正文

AsyncTask源码分析

要研究Android的AsyncTask之前,要先搞明白FutureTask和Executor类:

 FutureTask是什么:

FutureTask实际上是一个任务的操作类,它并不启动新线程,只是在自己所在线程上操作,任务的具体实现是构造FutureTask时提供的,实现自Callable<V>接口,FutureTask不知道具体的任务是什么,它只知道如何调度任务,如:

  • 如何启动任务:在FutureTask的run()方法中(实现自Runnable.run()),调用Callable.call()方法来启动任务,Callable.call()方法中是任务的具体实现;
  • 如何取消任务:在cancel()里,中断执行任务的线程,记录任务结束状态,并调用done()方法来执行用户实现的操作;
  • 如何返回任务的运行结果:如果任务还在执行,则阻塞线程(使用LockSupport.park()),直到任务结束才返回结果,用户可以通过get()方法来获取结果,同样当任务运行结束时,会调用down()来执行用户实现的操作。

使用FutureTask的好处是,更轻松的对任务进行管理,而不是像Runnable那样扔进线程后就啥也不能做了。

 Executor是什么:

Executor顾名思义是任务执行者,它不关心是什么任务,只关心如何执行任务。Executor是个Interface,具体如何执行任务要看怎么实现这个接口,你可以这样实现:

 class DirectExecutor implements Executor {
  @Override
public void execute(Runnable r) { r.run(); } }

也可以这样实现:

class ThreadPerTaskExecutor implements Executor {
  @Override
public void execute(Runnable r) { new Thread(r).start(); } }

这两种实现的区别显而易见,java文档还提供了另一个Executor实现的例子:

 class SerialExecutor implements Executor {
   final Queue tasks = new ArrayDeque();
   final Executor executor;
   Runnable active;

   SerialExecutor(Executor executor) {
     this.executor = executor;
   }
  @Override
public synchronized void execute(final Runnable r) { tasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); if (active == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((active = tasks.poll()) != null) { executor.execute(active); } } }

这个实现的意思是,严格按照用户提交的顺序来执行任务。Android的AsyncTask就使用了这个例子。

AsyncTask是如何实现的:

AsyncTask实现的关键地方在构造函数和executeOnExecutor()函数里。

  • 首先看下构造函数:
    public AsyncTask() {
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
          //任务的具体实现
return postResult(doInBackground(mParams)); } }; mFuture = new FutureTask<Result>(mWorker) { @Override protected void done() { try { postResultIfNotInvoked(get()); } catch (InterruptedException e) { android.util.Log.w(LOG_TAG, e); } catch (ExecutionException e) { throw new RuntimeException( "An error occured while executing doInBackground()", e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); } } }; }

 

代码中WorkerRunnable实现自Callable,所以mWorker就是任务的具体实现(call()中的doInBackground())。通过对FutureTask的说明可以知道,mFuture是mWorker的操作类,它不仅用来实现对AsyncTask任务的操作(cancel,get等),最主要的,实现了mWorker执行结束的操作:

    private void postResultIfNotInvoked(Result result) {
        final boolean wasTaskInvoked = mTaskInvoked.get();
        if (!wasTaskInvoked) {
            postResult(result);
        }
    }

    private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }

    private static final InternalHandler sHandler = new InternalHandler();

    private static class InternalHandler extends Handler {
        @SuppressWarnings({ "unchecked", "RawUseOfParameterizedType" })
        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult result = (AsyncTaskResult) msg.obj;
            switch (msg.what) {
            case MESSAGE_POST_RESULT:
                // There is only one result
                result.mTask.finish(result.mData[0]);
                break;
            case MESSAGE_POST_PROGRESS:
                result.mTask.onProgressUpdate(result.mData);
                break;
            }
        }
    }

    private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }

FutureTask和Handler共同实现了任务结束的操作,代码很简单,不赘述。

  • 接下来是executeOnExecutor()函数的实现:
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

    public final AsyncTask<Params, Progress, Result> executeOnExecutor(
            Executor exec, Params... params) {
        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;

        onPreExecute();

        mWorker.mParams = params;
        exec.execute(mFuture);

        return this;
    }

AsyncTask是通过execute或executeOnExecutor启动的,通过上边对Executor的介绍可以知道,在executeOnExecutor()中的exec.execute(mFuture)这一行就是根据exec的实现方式来启动mFuture了,问题的关键是exec是如何实现execute()的。在execute中可以看到AsyncTask提供了一个默认的sDefaultExecutor,这个sDefaultExecutor是什么呢:

    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

    private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;

        public synchronized void execute(final Runnable r) {
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive == null) {
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext() {
            if ((mActive = mTasks.poll()) != null) {
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }

默认情况下,sDefaultExecutor就是SerialExecutor类,通过源码可以看到,SerialExecutor是一个严格按照用户提交顺序来执行任务的执行者,其中scheduleNext()函数用来启动下一个任务:

 

        protected synchronized void scheduleNext() {
            if ((mActive = mTasks.poll()) != null) {
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }

 

THREAD_POOL_EXECUTOR就是真正启动任务的Executor:
    public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
            CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS,
            sPoolWorkQueue, sThreadFactory);

ThreadPoolExecutor是java自己实现的一种Executor,顾名思义,是个提供线程池的Executor。

由上可以知道,当调用AsyncTask的execute()函数时,AsyncTask会按用户提交任务的顺序,在线程池里串行的执行任务(当前任务运行结束,再运行下一个)。

当然用户也可以提供自己的Executor来改变AsyncTask的运行方式。

 

 

转载于:https://www.cnblogs.com/coding-way/p/3578897.html

相关文章:

  • 如何修改ubuntu的用户名和主机名称
  • NFS服务器配置
  • PHP输出字节流带上BOM
  • InnoDB体系架构
  • 【2016-7-20】 Linux基础知识初识
  • bugzilla Incorrect key file for table './bugs/bugs_fulltext.MYI
  • 反射机制
  • 移动端基于HTML模板和JSON数据的JavaScript交互
  • 度分秒的正则表达式
  • JQuery 网页选项卡制作
  • UML类图几种关系的总结
  • groovy-file2
  • linux 软件包管理
  • 【转】排名Top 16的Java实用类库
  • 繁杂产生利润 但与你无关-【软件和信息服务】2014.03
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • .pyc 想到的一些问题
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • Android Volley源码解析
  • ng6--错误信息小结(持续更新)
  • python大佬养成计划----difflib模块
  • 给第三方使用接口的 URL 签名实现
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 记录:CentOS7.2配置LNMP环境记录
  • 你真的知道 == 和 equals 的区别吗?
  • 扑朔迷离的属性和特性【彻底弄清】
  • 前端js -- this指向总结。
  • 前端工程化(Gulp、Webpack)-webpack
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 手写双向链表LinkedList的几个常用功能
  • 数组的操作
  • 双管齐下,VMware的容器新战略
  • 一起参Ember.js讨论、问答社区。
  • 异步
  • 终端用户监控:真实用户监控还是模拟监控?
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • !!java web学习笔记(一到五)
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • #HarmonyOS:基础语法
  • $.ajax()
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转) Android中ViewStub组件使用
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • .NET学习全景图
  • @Builder用法
  • [3D游戏开发实践] Cocos Cyberpunk 源码解读-高中低端机性能适配策略
  • [ACTF2020 新生赛]Include
  • [C++]四种方式求解最大子序列求和问题
  • [C语言][C++][时间复杂度详解分析]二分查找——杨氏矩阵查找数字详解!!!
  • [docker]docker网络-直接路由模式
  • [ffmpeg] x264 配置参数解析