AsyncTask execute 那些事

大家都用过AsyncTask,也都知道通过AsyncTask可以比较方便的从事异步操作,并且可以随时更新UI,是一个比较理想的异步事物处理方案。
AsyncTask是如何执行的?
所有人都会告诉我 execute,谁不知道啊!
我最近就遇到了一个问题,通过AsyncTask execute方法,进行异步操作,可是等了好久,doInBackground 也没有执行,更别提操作的结果了。为啥呢?
自己动手,丰衣足食,还是来找源码吧。
首先来看execute的方法体

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

遇到方法重载了,其中sDefaultExecutor 应该是个线程池,我们看一下这个线程池

    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
     /**
     * 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();

在继续跟进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);
            }
        }
    }

在结合代码,不难发现,这个东西是(SerialExecutor)个假的线程池,实际上顺序执行的,当上一个task未执行完,就不会执行下一个。换句话说,这是一个队列(先入先出),前面的没与执行完,后面的是不会被执行的。所以,当任务多的时候,新建的任务会被延后,所以等待的时间就会变长。

那你可能说,即使有一个队列,但对我new一个AysncTask有影响吗?
有的,因为sDefaultExecutor是AsyncTask的 static 属性,是所有AsyncTask对象共享的,故当使用AsyncTask execute方法的情况下,都可能出现这样的问题。
那应该怎么解决呢?
其实AsyncTask里面真的有一个线程池,只要我们在执行异步任务的时候,使用这个真正的线程池,就可以解决这个问题。
在调用时使用如下方法即可

executeOnExecutor(Executor exec, Params... params) 

exec对象使用AsyncTask.THREAD_POOL_EXECUTOR
参考示例如下(假设params 参数类型为String)

execteOnExcecutor(AsyncTask.THREAD_POOL_EXECUTOR,“cbl”)

好了,此篇到此为止了,希望能帮助朋友们解决实际问题

你可能感兴趣的:(Android,随笔)