AsyncTask utilise un modèle de pool de threads pour exécuter les éléments à partir de doInBackground (). Le problème est initialement (dans les premières versions du système d'exploitation Android), la taille du pool n'était que de 1, ce qui signifie qu'il n'y a pas de calculs parallèles pour un tas d'AsyncTasks. Mais plus tard, ils ont corrigé cela et maintenant la taille est de 5, donc au plus 5 AsyncTasks peuvent s'exécuter simultanément. Malheureusement, je ne me rappelle pas dans quelle version exactement ils ont changé cela.
METTRE À JOUR:
Voici ce que l'API actuelle (2012-01-27) dit à ce sujet:
Lors de leur introduction, les AsyncTasks ont été exécutés en série sur un seul thread d'arrière-plan. À partir de DONUT, cela a été changé en un pool de threads permettant à plusieurs tâches de fonctionner en parallèle. Après HONEYCOMB, il est prévu de le remplacer par un seul thread pour éviter les erreurs d'application courantes causées par l'exécution parallèle. Si vous voulez vraiment une exécution parallèle, vous pouvez utiliser la version executeOnExecutor (Executor, Params ...) de cette méthode avec THREAD_POOL_EXECUTOR; cependant, voir les commentaires pour les avertissements sur son utilisation.
DONUT est Android 1.6, HONEYCOMB est Android 3.0.
MISE À JOUR: 2
Voir le commentaire de kabuko
de Mar 7 2012 at 1:27
.
Il s'avère que pour les API où "un pool de threads permettant à plusieurs tâches d'opérer en parallèle" est utilisé (à partir de 1.6 et se terminant sur 3.0), le nombre d'AsyncTasks exécutés simultanément dépend du nombre de tâches qui ont déjà été passées pour exécution, mais n'ont pas encore terminé leur doInBackground()
.
Ceci est testé / confirmé par moi sur 2.2. Supposons que vous ayez une AsyncTask personnalisée qui ne dort qu'une seconde doInBackground()
. Les AsyncTasks utilisent une file d'attente de taille fixe en interne pour stocker les tâches retardées. La taille de la file d'attente est 10 par défaut. Si vous lancez 15 vos tâches personnalisées d'affilée, les 5 premières entreront leur doInBackground()
, mais le reste attendra dans une file d'attente un thread de travail gratuit. Dès que l'un des 5 premiers se termine et libère ainsi un thread de travail, une tâche de la file d'attente démarre l'exécution. Donc, dans ce cas, au plus 5 tâches seront exécutées simultanément. Cependant, si vous démarrez 16 vos tâches personnalisées d'affilée, les 5 premiers entreront leurs doInBackground()
, les 10 autres entreront dans la file d'attente, mais pour le 16, un nouveau thread de travail sera créé afin qu'il démarre immédiatement. Donc, dans ce cas, au plus 6 tâches s'exécuteront simultanément.
Le nombre de tâches pouvant être exécutées simultanément est limité. Puisqu'il AsyncTask
utilise un exécuteur de pool de threads avec un nombre maximum limité de threads de travail (128) et que la file d'attente des tâches retardées a une taille fixe de 10, si vous essayez d'exécuter plus de 138 vos tâches personnalisées, l'application se bloquera java.util.concurrent.RejectedExecutionException
.
Depuis la version 3.0, l'API permet d'utiliser votre exécuteur de pool de threads personnalisé via la AsyncTask.executeOnExecutor(Executor exec, Params... params)
méthode. Cela permet, par exemple, de configurer la taille de la file d'attente des tâches retardées si la valeur par défaut 10 n'est pas celle dont vous avez besoin.
Comme le mentionne @Knossos, il existe une option à utiliser à AsyncTaskCompat.executeParallel(task, params);
partir de la bibliothèque de support v.4 pour exécuter des tâches en parallèle sans se soucier du niveau de l'API. Cette méthode est devenue obsolète au niveau de l'API 26.0.0.
MISE À JOUR: 3
Voici une application de test simple pour jouer avec un certain nombre de tâches, exécution série ou parallèle: https://github.com/vitkhudenko/test_asynctask
MISE À JOUR: 4 (merci @penkzhou de l'avoir signalé)
À partir d'Android 4.4, le AsyncTask
comportement diffère de celui décrit dans la section MISE À JOUR: 2 . Il existe un correctif pour éviter AsyncTask
de créer trop de threads.
Avant Android 4.4 (API 19) AsyncTask
avait les champs suivants:
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);
Dans Android 4.4 (API 19), les champs ci-dessus sont modifiés comme suit:
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);
Cette modification augmente la taille de la file d'attente à 128 éléments et réduit le nombre maximal de threads au nombre de cœurs de processeur * 2 + 1. Les applications peuvent toujours soumettre le même nombre de tâches.