AsyncTask usa un patrón de grupo de subprocesos para ejecutar el material desde doInBackground (). El problema es inicialmente (en las primeras versiones del sistema operativo Android) el tamaño del grupo era solo 1, lo que significa que no hay cálculos paralelos para un montón de AsyncTasks. Pero luego lo arreglaron y ahora el tamaño es 5, por lo que a lo sumo 5 AsyncTasks pueden ejecutarse simultáneamente. Desafortunadamente no recuerdo en qué versión cambiaron exactamente eso.
ACTUALIZAR:
Esto es lo que la API actual (2012-01-27) dice sobre esto:
Cuando se introdujo por primera vez, las AsyncTasks se ejecutaron en serie en un único subproceso en segundo plano. Comenzando con DONUT, esto se cambió a un grupo de subprocesos que permite que varias tareas funcionen en paralelo. Después de HONEYCOMB, se planea volver a cambiar esto a un solo subproceso para evitar errores de aplicación comunes causados por la ejecución paralela. Si realmente desea una ejecución paralela, puede usar la versión executeOnExecutor (Executor, Params ...) de este método con THREAD_POOL_EXECUTOR; sin embargo, vea comentarios allí para advertencias sobre su uso.
DONUT es Android 1.6, HONEYCOMB es Android 3.0.
ACTUALIZACIÓN: 2
Ver el comentario kabuko
de Mar 7 2012 at 1:27
.
Resulta que para las API donde se usa "un grupo de subprocesos que permite que múltiples tareas operen en paralelo" (comenzando desde 1.6 y terminando en 3.0), el número de AsyncTasks que se ejecutan simultáneamente depende de cuántas tareas ya se hayan pasado para la ejecución, pero No he terminado su doInBackground()
todavía.
Esto es probado / confirmado por mí en 2.2. Supongamos que tiene una AsyncTask personalizada que solo duerme un segundo doInBackground()
. AsyncTasks utiliza una cola de tamaño fijo internamente para almacenar tareas retrasadas. El tamaño de la cola es 10 por defecto. Si comienza 15 sus tareas personalizadas en una fila, entonces las primeras 5 ingresarán sus doInBackground()
, pero el resto esperará en una cola para un hilo de trabajo libre. Tan pronto como alguno de los primeros 5 finalice y, por lo tanto, libere un subproceso de trabajo, se iniciará una tarea de la cola. Entonces, en este caso, como máximo 5 tareas se ejecutarán simultáneamente. Sin embargo, si comienza 16 sus tareas personalizadas en una fila, luego las primeras 5 ingresarán a las suyas doInBackground()
, las 10 restantes entrarán en la cola, pero para el 16 se creará un nuevo subproceso de trabajo para que comience la ejecución de inmediato. Entonces, en este caso, como máximo 6 tareas se ejecutarán simultáneamente.
Hay un límite de cuántas tareas se pueden ejecutar simultáneamente. Dado que AsyncTask
utiliza un ejecutor de grupo de subprocesos con un número máximo limitado de subprocesos de trabajo (128) y la cola de tareas retrasadas tiene un tamaño fijo de 10, si intenta ejecutar más de 138 sus tareas personalizadas, la aplicación se bloqueará java.util.concurrent.RejectedExecutionException
.
A partir de 3.0, la API permite utilizar su ejecutor de grupo de subprocesos personalizado a través del AsyncTask.executeOnExecutor(Executor exec, Params... params)
método. Esto permite, por ejemplo, configurar el tamaño de la cola de tareas retrasadas si el valor predeterminado 10 no es lo que necesita.
Como @Knossos menciona, hay una opción para usar AsyncTaskCompat.executeParallel(task, params);
desde la biblioteca de soporte v.4 para ejecutar tareas en paralelo sin molestarse con el nivel de API. Este método quedó en desuso en el nivel de API 26.0.0.
ACTUALIZACIÓN: 3
Aquí hay una aplicación de prueba simple para jugar con varias tareas, ejecución en serie o en paralelo: https://github.com/vitkhudenko/test_asynctask
ACTUALIZACIÓN: 4 (gracias @penkzhou por señalar esto)
A partir de Android 4.4 se AsyncTask
comporta de manera diferente a lo que se describió en la sección ACTUALIZACIÓN: 2 . Hay una solución para evitar AsyncTask
crear demasiados hilos.
Antes de Android 4.4 (API 19) AsyncTask
tenía los siguientes campos:
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);
En Android 4.4 (API 19) los campos anteriores se cambian a esto:
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);
Este cambio aumenta el tamaño de la cola a 128 elementos y reduce la cantidad máxima de subprocesos a la cantidad de núcleos de CPU * 2 + 1. Las aplicaciones aún pueden enviar la misma cantidad de tareas.