gpt4 book ai didi

android - 同时运行多个 AsyncTask —— 不可能吗?

转载 作者:IT老高 更新时间:2023-10-28 12:51:24 29 4
gpt4 key购买 nike

我正在尝试同时运行两个 AsyncTask。 (平台为Android 1.5,HTC Hero。)但是,只有第一个被执行。这是一个简单的 fragment 来描述我的问题:

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 任务会产生输出。

我是否遗漏了一些明显的东西和/或做了一些愚蠢的事情?不能同时运行两个 AsyncTask 吗?

编辑:我意识到有问题的手机运行 Android 1.5,我更新了问题描述。因此。运行 Android 2.1 的 HTC Hero 没有这个问题。嗯……

最佳答案

AsyncTask 使用线程池模式来运行来自 doInBackground() 的内容。问题最初是(在早期的 Android 操作系统版本中)池大小仅为 1,这意味着一堆 AsyncTask 没有并行计算。但后来他们修复了这个问题,现在大小为 5,所以最多 5 个 AsyncTask 可以同时运行。不幸的是,我不记得他们在哪个版本中改变了这一点。

更新:

这是当前 (2012-01-27) API 对此的说明:

When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. After HONEYCOMB, it is planned to change this back to a single thread to avoid common application errors caused by parallel execution. If you truly want parallel execution, you can use the executeOnExecutor(Executor, Params...) version of this method with THREAD_POOL_EXECUTOR; however, see commentary there for warnings on its use.

DONUT 是 Android 1.6,HONEYCOMB 是 Android 3.0。

更新:2

查看 kabukoMar 7 2012 1:27 发表的评论。

事实证明,对于使用“允许多个任务并行运行的线程池”的 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 部分中描述的不同。有is a fix防止 AsyncTask 创建过多线程。

在 Android 4.4 (API 19) AsyncTask 之前有以下字段:

private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(10);

在 Android 4.4 (API 19) 中,上述字段更改为:

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);

此更改将队列大小增加到 128 项,并将最大线程数减少到 CPU 内核数 * 2 + 1。应用仍然可以提交相同数量的任务。

关于android - 同时运行多个 AsyncTask —— 不可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4068984/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com