我正在尝试同时运行两个 AsyncTasks。 (平台是 Android 1.5,HTC Hero。)但是,只有第一个被执行。这是一个简单的片段来描述我的问题:
public class AndroidJunk extends Activity {
class PrinterTask extends AsyncTask<String, Void, Void> {
protected Void doInBackground(String ... x) {
while (true) {
System.out.println(x[0]);
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new PrinterTask().execute("bar bar bar");
new PrinterTask().execute("foo foo foo");
System.out.println("onCreate() is done.");
}
}
我期望的输出是:
onCreate() is done.
bar bar bar
foo foo foo
bar bar bar
foo foo foo
等等。但是,我得到的是:
onCreate() is done.
bar bar bar
bar bar bar
bar bar bar
第二个 AsyncTask 永远不会被执行。如果我更改 execute() 语句的顺序,则只有 foo 任务会产生输出。
我是否在这里遗漏了一些明显的东西和/或做了一些愚蠢的事情?不能同时运行两个 AsyncTasks 吗?
编辑:我意识到有问题的手机运行 Android 1.5,我更新了问题描述。因此。运行 Android 2.1 的 HTC Hero 没有这个问题。嗯…
原文由 rodion 发布,翻译遵循 CC BY-SA 4.0 许可协议
AsyncTask 使用线程池模式来运行来自 doInBackground() 的内容。问题最初是(在早期的 Android 操作系统版本中)池大小仅为 1,这意味着一堆 AsyncTask 没有并行计算。但后来他们修复了这个问题,现在大小为 5,所以最多 5 个 AsyncTask 可以同时运行。不幸的是,我不记得他们到底在哪个版本中改变了这一点。
更新:
以下是当前 (2012-01-27) API 对此的说明:
DONUT 是 Android 1.6,HONEYCOMB 是 Android 3.0。
更新:2
请参阅来自
Mar 7 2012 at 1:27
的 ---kabuko
的评论。事实证明,对于使用“允许多个任务并行运行的线程池”的 API(从 1.6 开始,到 3.0 结束),同时运行的 AsyncTask 的数量取决于已经传递了多少任务来执行,但是还没有完成他们的
doInBackground()
。这是我在 2.2 上测试/确认的。假设您有一个自定义 AsyncTask,它只在
doInBackground()
中休眠一秒钟。 AsyncTask 在内部使用固定大小的队列来存储延迟任务。队列大小默认为 10。如果您连续启动 15 个自定义任务,那么前 5 个将进入它们的doInBackground()
,但其余的将在队列中等待空闲的工作线程。只要前 5 个任务中的任何一个完成,从而释放一个工作线程,队列中的一个任务就会开始执行。所以在这种情况下,最多 5 个任务将同时运行。但是,如果您连续启动 16 个自定义任务,那么前 5 个将进入它们的doInBackground()
,其余 10 个将进入队列,但是对于第 16 个,将创建一个新的工作线程,因此它将立即开始执行。所以在这种情况下,最多 6 个任务将同时运行。可以同时运行多少个任务是有限制的。由于
AsyncTask
使用的线程池执行器具有有限的最大工作线程数 (128) 并且延迟任务队列的大小固定为 10,如果您尝试执行超过 138 个自定义任务,应用程序将崩溃java.util.concurrent.RejectedExecutionException
。从 3.0 开始,API 允许通过
AsyncTask.executeOnExecutor(Executor exec, Params... params)
方法使用您的自定义线程池执行器。例如,如果默认 10 不是您需要的,这允许配置延迟任务队列的大小。正如@Knossos 提到的,有一个选项可以使用支持v.4 库中的
AsyncTaskCompat.executeParallel(task, params);
来并行运行任务,而无需担心API 级别。此方法在 API 级别 26.0.0 中已弃用。更新:3
这是一个简单的测试应用程序,用于处理任务数量、串行与并行执行: https ://github.com/vitkhudenko/test_asynctask
更新:4 (感谢@penkzhou 指出这一点)
从 Android 4.4 开始
AsyncTask
的行为与 UPDATE: 2 部分中描述的不同。有 一个修复程序 可以防止AsyncTask
创建太多线程。在 Android 4.4 (API 19) 之前
AsyncTask
有以下字段:在 Android 4.4 (API 19) 中,上述字段更改为:
此更改将队列大小增加到 128 个项目,并将最大线程数减少到 CPU 内核数 * 2 + 1。应用程序仍然可以提交相同数量的任务。