异步执行--AsyncTask

作者: 尔乐 | 来源:发表于2017-12-13 16:54 被阅读43次

    在类的定义说明中有这样一句话

    大概意思是你只能使用AsyncTask执行一些运行周期短的操作(最多只有几秒)如果是长周期的方法,最好使用Executor,ThreadPoolExecutor 等。

    AsyncTasks should ideally be
     * used for short operations (a few seconds at the most.) If you need to keep threads
     * running for long periods of time, it is highly recommended you use the various APIs
     * provided by the <code>java.util.concurrent</code> package such as {@link Executor},
     * {@link ThreadPoolExecutor} and {@link FutureTask}
    
    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
            return executeOnExecutor(sDefaultExecutor, params);
        }
    

    AsyncTask 执行execute的时候采用的是 sDefaultExecutor 作为executor,sDefaultExecutor默认的指向

    /**
         * An {@link Executor} that executes tasks one at a time in serial
         * order.  This serialization is global to a particular process.
         */
        public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
    ...
    ...
        private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
    

    下面来看一下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);
                }
            }
        }
    

    这里很有意思,在SerialExecutor scheduleNext的方法里调用了 THREAD_POOL_EXECUTOR 的execute(mActive)

    mActive 实际上是 
            new Runnable() {
                    public void run() {
                        try {
                            r.run();
                        } finally {
                            scheduleNext();
                        }
                    }
                }
    

    也就是AsyncTask通过 SerialExecutor 调度,使用 mTasks缓存,但是执行的时候,采用的是THREAD_POOL_EXECUTOR,大家不难看出,需要线程执行完毕的时候,才会在finally里走进scheduleNext(),继续执行。

    在这里要说一下,如果没用过AsyncTask 的同学,可能没办法理解这个mTasks什么情况下会有缓存,会有多个值,大家可能注意到了 execute(Params... params),然后并不是这里。这个地方的参数params在后面会讲到,他是作为一个数组传递给了doInBackground方法。

    那么这里是在什么情况下会有缓存数据呢?看下面定义

     private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
    //大家看定义,这是一个静态的Executor也就是说进程中所有的AsyncTask都是通过同一个sDefaultExecutor 来调度的。
    

    说到这里,大家可能明白了开篇说的那句话,如果执行时间比较长,那么AsyncTask的sDefaultExecutor就会被卡住,后面的任务都无法执行了。

    在类的构造方法里,初始化了两个变量,其中一个是mWorker,他是一个Callable,他的call方法,执行了 result = doInBackground(mParams);并且最终调用了 postResult(result);通知用户。

    mWorker = new WorkerRunnable<Params, Result>() {
                public Result call() throws Exception {
                    mTaskInvoked.set(true);
                    Result result = null;
                    try {
                        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                        //noinspection unchecked
                        result = doInBackground(mParams);
                        Binder.flushPendingCommands();
                    } catch (Throwable tr) {
                        mCancelled.set(true);
                        throw tr;
                    } finally {
                        postResult(result);
                    }
                    return result;
                }
            };
    

    好了,就这样,先说到这里,大家感兴趣不防测试验证一下。

    相关文章

      网友评论

        本文标题:异步执行--AsyncTask

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