异步执行--AsyncTask

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

大概意思是你只能使用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;
            }
        };

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

    原文作者:尔乐
    原文地址: https://www.jianshu.com/p/4e297f6a78a2
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞