AsyncTask 只能执行一次

讨论两个问题:

第一个问题:一个AsyncTask对象只能被执行一次,即只能调用一次execute;

第二个问题:既然一个AsyncTask对象只能被执行一次,为什么AsyncTask还要用线程池;


第一个问题

刚开始用AsyncTask的时候就知道一个AsyncTask对象只能被执行一次,即只能调用一次execute;

其实对这个概念是模糊的,一直再用也就没有关注,今天晚上特地研究了一下到底是什么意思,也就是代码怎么实现才算是一次,怎么实现算是多次;

下面用代码说明:

第一种情况:同时直接都execute

AsyncTask 只能执行一次_第1张图片

通过按钮点击触发上面的方法,控制台得到的结果是:

第二种情况:先让myAsyncTask执行完任务,然后我再执行execute;


通过按钮点击触发上面的方法,任务执行为三秒,控制台得到的结果是:

AsyncTask 只能执行一次_第2张图片

上面两个例子就很显然了,一个AsyncTask对象只能执行一次,关键点就在“一个对象”上;

佐证

如果到这还不明那就看下这个例子,同样是MyAsyncTask对象,但是我new多次,每new一次就代表着一个新的对象,看代码:

AsyncTask 只能执行一次_第3张图片

同样看下点击按钮后控制台的信息:

AsyncTask 只能执行一次_第4张图片

到这这里就很清楚了,一个AsyncTask对象只能执行一次。

注:我一直纠结的问题就是一个AsyncTask只能执行一次,我恰恰是忽略“对象”两个字(这也就是我一直单着的原因吧,哈哈哈)。

下面是MyAsyncTask,这个文章中的MyAsyncTask都是同一个:

AsyncTask 只能执行一次_第5张图片


第二个问题

在同一进程下的所有AsyncTask的任务都会到达同一个任务对队列:

我们从 new MyAsyncTask("onlyonce 1").execute(); 说起,现在看下源码

    @MainThread
    public final AsyncTask execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

我们看到了executor调用的是executorOnExecutor在来看下它的源码

    @MainThread
    public final AsyncTask 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;
    }

主要看exec.execute(mFuture)这一行。

exec是什么呢?从execute函数里面的实现就可以看到,exec是sDefaultExecutor,那么sDefaultExecutor是什么玩意呢?

从一下代码可以清楚的看到:

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

sDefaultExecutor是SerialExecutor的一个实例,而且它是个静态变量。也就是说,一个进程里面所有AsyncTask对象都共享同一个SerialExecutor对象。

    private static class SerialExecutor implements Executor {
        final ArrayDeque mTasks = new ArrayDeque();
        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);
            }
        }
    }
代码本身很简单,从execute里面就能看出,异步任务r被放到了ArrayDeque对象mTasks中,然后通过scheduleNext()来从mTasks里面得到一个任务去一个后台线程执行。
在一个异步任务执行后,再次调用scheduleNext来执行下一个任务(run函数)。
所以,很清楚,其实SerialExecutor是一个一个执行任务的,而所有的AsyncTask对象又共享同一个SerialExecutor对象(静态成员)。







你可能感兴趣的:(Android)