【问题标题】:Asynctask SerialExecutor is not serially executingAsynctask SerialExecutor 没有串行执行
【发布时间】:2013-12-17 16:57:53
【问题描述】:

我创建了以下 2 个异步任务

public class MyAsynctaskWithDelay extends AsyncTask<String,Void,Void> {

    @Override
    protected Void doInBackground(String... arg0) {
        // TODO Auto-generated method stub
        System.out.println(arg0[0] + "before sleeping of AsyctaskWithDelay..");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(arg0[0] + "after sleeping of AsyctaskWithDelay..");
        //System.out.println(arg0[0]);
        return null;

    }

}

public class MyAsynctaskWithNoDelayLoop extends AsyncTask<String,Void,Void> {

    @Override
    protected Void doInBackground(String... arg0) {
        // TODO Auto-generated method stub
        System.out.println(arg0[0] + " The task with no delay...");
        //System.out.println(arg0[0]);
        return null;

    }
}

然后在主要活动中我做了如下操作:

        MyAsynctaskWithDelay asynctask1 = new MyAsynctaskWithDelay();
        MyAsynctaskWithDelay asynctask2 = new MyAsynctaskWithDelay();
        MyAsynctaskWithNoDelayLoop asynctask3 = new MyAsynctaskWithNoDelayLoop();
        MyAsynctaskWithNoDelayLoop asynctask4 = new MyAsynctaskWithNoDelayLoop();


        asynctask1.execute("Asynctask 1");
        asynctask2.execute("Asynctask 2");
        asynctask3.execute("Asynctask 3");
        asynctask4.execute("Asynctask 4");

因此根据SerialExecutor的定义,任务应该按照execute方法被调用的顺序执行,后台任务不应该被抢占。

但是,我已经运行了这个应用程序并得到了以下结果。

12-02 09:18:20.526: I/System.out(402): Asynctask 1before sleeping of AsyctaskWithDelay..
12-02 09:18:20.576: I/System.out(402): Asynctask 2before sleeping of AsyctaskWithDelay..
12-02 09:18:20.586: I/System.out(402): Asynctask 3 The task with no delay...
12-02 09:18:20.586: I/System.out(402): Asynctask 4 The task with no delay...
12-02 09:18:30.582: I/System.out(402): Asynctask 1after sleeping of AsyctaskWithDelay..
12-02 09:18:30.703: I/System.out(402): Asynctask 2after sleeping of AsyctaskWithDelay..

很明显,前两个任务在 doinbackground 方法中被抢占了,这显然不是预期的。

请澄清我的疑问,以便我可以回答我自己关于 Asynctask Serialexecutor 工作原理的问题。

如果我们深入研究Android的Serial Executor类的源代码就会发现

 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);
            }
        }
    }

如果我们看一下execute函数的下面部分写成

 mTasks.offer(new Runnable() {
                    public void run() {
                        try {
                            r.run();
                        } finally {
                            scheduleNext();
                        }
                    }
                });

我们会知道,每次调用执行函数时,它都会创建一个新线程,并在该线程内执行后台任务。这意味着任何长时间运行的后台任务都可以被另一个执行的不同 Asynctask 实例的后台任务抢占。那为什么叫Serial Executor呢。

【问题讨论】:

  • 我没有看到你以任何方式使用SerialExecutor..
  • 如您所知,默认执行器是串行执行器
  • 我已经解决了一些疑问。由于 SERIAL-EXECUTOR 是一个 final 静态字段,它将被同一个 Asynctask 的所有对象共享。随之而来的是执行函数之前的 Synchronized 关键字。因此它作为一个串行执行器工作。但是,从我的Android应用程序的结果中,我们可以看到一些后台任务正在被抢占...请您解释一下...
  • 我明白了。我的 minSDKversion 是 8。我现在已经达到了 14。它工作正常。很抱歉在没有纠正自己的情况下指责 Android 框架......
  • 这是我关于 Android Asynctask Internal vis-a-vis Half Sync Half Async 模式的讨论...docs.google.com/document/d/…

标签: android android-asynctask


【解决方案1】:

AsyncTask 是线程的一种简单替代品。所以同样的线程(无论是否串行执行器)你不应该依赖于它们的执行顺序。如果你只需要让它们连续,那么你必须自己处理这一切。

【讨论】:

  • 您确定您的评论吗?我认为 Asynctask 很好地解决了线程问题......它也是 Android 框架的重要组成部分......
  • 我不是说 AsyncTask 不好我是说线程的执行是相互独立的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-15
  • 1970-01-01
相关资源
最近更新 更多