我创建了以下2个Asynctasks
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);
}
}
}
如果我们将执行函数的以下部分视为
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
我们将知道,每次调用执行函数时,它都会创建一个新线程,并在该线程内执行后台任务。这意味着任何长时间运行的后台任务都可以被另一个不同的Asynctask实例的执行后台任务抢占。那么为什么它被称为Serial Executor。
答案 0 :(得分:0)
AsyncTask
是线程的简单替代品。所以线程(无论是否是串行执行程序)你不应该依赖于它们的执行顺序。如果你只需要将它们串行化,那么你必须自己处理它们。