AsyncTask使用线程池模式来运行来自doInBackground()的东西。问题是最初(在早期的Android OS版本中)池大小只有1,这意味着一堆asynctask没有并行计算。但后来他们修复了这个问题,现在大小是5,所以最多5个AsyncTasks可以同时运行。不幸的是,我不记得他们在哪个版本中改变了这一点。
更新:
以下是当前(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
请看歌舞伎2012年3月7日1:27的评论。
事实证明,对于使用“允许多个任务并行操作的线程池”的api(从1.6开始到3.0结束),同时运行的AsyncTasks的数量取决于有多少任务已经被传递执行,但还没有完成它们的doInBackground()。
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。
从3.0开始,API允许通过AsyncTask使用自定义线程池执行器。executeOnExecutor(Executor exec, Params…params)方法。例如,如果默认的10不是您需要的,这允许配置延迟任务队列的大小。
正如@Knossos提到的,有一个选项可以使用AsyncTaskCompat。executeParallel(任务,params);从支持v.4库并行运行任务,而无需担心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有以下字段:
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。应用程序仍然可以提交相同数量的任务。