在同一时间运行多个AsyncTasks - 不可能? [英] Running multiple AsyncTasks at the same time -- not possible?

查看:118
本文介绍了在同一时间运行多个AsyncTasks - 不可能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在同一时间运行两个AsyncTasks。 (平台的是Android 1.5,HTC Hero的。) 但是,仅第一被执行。这里有一个简单的代码段来形容我的问题:

I'm trying to run two AsyncTasks at the same time. (Platform is Android 1.5, HTC Hero.) However, only the first gets executed. Here's a simple snippet to describe my problem:

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

我期望的输出是:

The output I expect is:

onCreate() is done.
bar bar bar
foo foo foo
bar bar bar
foo foo foo

等。不过,我得到的是:

And so on. However, what I get is:

onCreate() is done.
bar bar bar
bar bar bar
bar bar bar

第二AsyncTask的永远不会被执行。如果我改变的execute()语句的顺序,只有FOO任务将产生输出。

The second AsyncTask never gets executed. If I change the order of the execute() statements, only the foo task will produce output.

我缺少明显的东西在这里和/或做一些愚蠢的事?它是不可能在同一时间运行两个AsyncTasks?

Am I missing something obvious here and/or doing something stupid? Is it not possible to run two AsyncTasks at the same time?

编辑:我的问题,实现了手机运行Android 1.5,我更新了问题DESCR。因此。我没有这个问题了HTC Hero的运行Android 2.1。嗯...

I realized the phone in question runs Android 1.5, I updated the problem descr. accordingly. I don't have this problem with an HTC Hero running Android 2.1. Hmmm ...

推荐答案

AsyncTask的使用从doInBackground运行的东西,一个线程池()。问题是最初(在早期的Andr​​oid操作系统版本)池大小只是1,这意味着没有并行计算的一堆AsyncTasks的。但是后来它们固定的和现在的大小是5,所以至多5 AsyncTasks可以同时运行。不幸的是,我不记得是什么版本正是他们改变了这一切。

AsyncTask uses a thread pool pattern for running the stuff from doInBackground(). The issue is initially (in early Android OS versions) the pool size was just 1, meaning no parallel computations for a bunch of AsyncTasks. But later they fixed that and now the size is 5, so at most 5 AsyncTasks can run simultaneously. Unfortunately I don't remember in what version exactly they changed that.

更新:

下面是电流(2012-01-27)AP​​I上说的:

Here is what current (2012-01-27) API says on this:

在首次推出,AsyncTasks是连续在一个后台线程中执行。与DONUT开始,此改变为线程允许多个任务,以在并行操作的一个池。蜂窝后,计划改变这种回单个线程以避免由并行执行常见的应用程序的错误。如果你真的想并行执行,则可以使用executeOnExecutor(执行器,参数...)版本,此方法THREAD_POOL_EXECUTOR的;但是,看到的评论有关于它的使用警告。

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,蜂窝的是Android 3.0。

DONUT is Android 1.6, HONEYCOMB is Android 3.0.

更新:2

请参阅从注释由 kabuko 3月7日在1:27

See the comment by kabuko from Mar 7 at 1:27.

事实证明,原料药,其中线程允许多个任务并行操作的一池的使用(从1.6开始和3.0结尾)同时运行AsyncTasks数量取决于有多少任务已经通过执行了,但还没有完成他们的 doInBackground()呢。

It turns out that for APIs where "a pool of threads allowing multiple tasks to operate in parallel" is used (starting from 1.6 and ending on 3.0) the number of simultaneously running AsyncTasks depends on how many tasks have been passed for execution already, but have not finished their doInBackground() yet.

这是测试/ 2.2上证实了我。假设你有一个只是睡觉第二的自定义的AsyncTask doInBackground()。 AsyncTasks使用固定大小的队列内部,用于存储延迟任务。队列的大小,默认为10。如果你在一排15开始您的自定义任务,则前5个进入他们的 doInBackground(),但其余的将在等待一个免费的工作线程队列中。只要任何所述第一5饰面,从而释放出工作线程,从队列的任务​​将开始执行。因此,在这种情况下,至多5任务将同时运行。但是,如果你在一排开始16自定义任务,则前5个进入他们的 doInBackground(),其余10将进入队列,但第16新工作线程将被创建的,因此它会立即开始执行。因此,在这种情况下,至多6任务将同时运行。

This is tested/confirmed by me on 2.2. Suppose you have a custom AsyncTask that just sleeps a second in doInBackground(). AsyncTasks use a fixed size queue internally for storing delayed tasks. Queue size is 10 by default. If you start 15 your custom tasks in a row, then first 5 will enter their doInBackground(), but the rest will wait in a queue for a free worker thread. As soon as any of the first 5 finishes, and thus releases a worker thread, a task from the queue will start execution. So in this case at most 5 tasks will run simultaneously. However if you start 16 your custom tasks in a row, then first 5 will enter their doInBackground(), the rest 10 will get into the queue, but for the 16th a new worker thread will be created so it'll start execution immediately. So in this case at most 6 tasks will run simultaneously.

有多少任务可同时运行的限制。由于的AsyncTask 使用与工作线程(128)的有限的最大数的线程池执行者和延迟任务队列的固定大小为10,如果您尝试执行超过138自定义任务的应用程序将与 java.util.concurrent.RejectedExecutionException 崩溃。

There is a limit of how many tasks can be run simultaneously. Since AsyncTask uses a thread pool executor with limited max number of worker threads (128) and the delayed tasks queue has fixed size 10, if you try to execute more than 138 your custom tasks the app will crash with java.util.concurrent.RejectedExecutionException.

从3.0开始API允许通过 AsyncTask.executeOnExecutor(遗嘱执行人EXEC,参数... PARAMS)的方法来使用你的自定义线程池执行者。这使得,例如,配置延迟任务队列的大小,如果默认的10是不是你所需要的。

Starting from 3.0 the API allows to use your custom thread pool executor via AsyncTask.executeOnExecutor(Executor exec, Params... params) method. This allows, for instance, to configure the size of the delayed tasks queue if default 10 is not what you need.

更新:3

下面是一个简单的测试应用程序与任务,串行与并行执行的一些玩法:<一href="https://github.com/vitkhudenko/test_asynctask">https://github.com/vitkhudenko/test_asynctask

Here is a simple test app to play with number of tasks, serial vs. parallel execution: https://github.com/vitkhudenko/test_asynctask

更新:4 (感谢@penkzhou指出了这一点)

UPDATE: 4 (thanks @penkzhou for pointing this out)

从Android 4.4系统开始的AsyncTask 行为不同于在什么样的更新被描述:2 部分。有<一href="https://android.googlesource.com/platform/frameworks/base/+/719c44e03b97e850a46136ba336d729f5fbd1f47%5E%21/#F0">is修复以prevent 的AsyncTask 从创建线程太多。

Starting from Android 4.4 AsyncTask behaves differently from what was described in UPDATE: 2 section. There is a fix to prevent AsyncTask from creating too many threads.

Android 4.4系统之前(API 19)的AsyncTask 有以下字段:

Before Android 4.4 (API 19) AsyncTask had the following fields:

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)上述领域都改成这样:

In Android 4.4 (API 19) the above fields are changed to this:

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。应用服务仍然可以提交任务的数量相同的数量。

This change increases the size of the queue to 128 items and reduces the maximum number of threads to the number of CPU cores * 2 + 1. Apps can still submit the same number of tasks.

这篇关于在同一时间运行多个AsyncTasks - 不可能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆