J'essaie d'exécuter deux AsyncTasks en même temps. (La plate-forme est Android 1.5, HTC Hero.) Cependant, seul le premier est exécuté. Voici un simple extrait pour décrire mon problème:
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.");
}
}
La sortie que j'attends est:
onCreate() is done.
bar bar bar
foo foo foo
bar bar bar
foo foo foo
Etc. Cependant, ce que je reçois est:
onCreate() is done.
bar bar bar
bar bar bar
bar bar bar
La deuxième AsyncTask n'est jamais exécutée. Si je change l'ordre des instructions execute (), seule la tâche foo produira une sortie.
Suis-je en train de manquer quelque chose d'évident ici et / ou de faire quelque chose de stupide? N'est-il pas possible d'exécuter deux AsyncTasks en même temps?
Edit: j'ai réalisé que le téléphone en question fonctionne sous Android 1.5, j'ai mis à jour le problème. en conséquence. Je n'ai pas ce problème avec un HTC Hero fonctionnant sous Android 2.1. Hmmm ...
Réponses:
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:
DONUT est Android 1.6, HONEYCOMB est Android 3.0.
MISE À JOUR: 2
Voir le commentaire de
kabuko
deMar 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 leurdoInBackground()
, 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 leursdoInBackground()
, 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 bloquerajava.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 éviterAsyncTask
de créer trop de threads.Avant Android 4.4 (API 19)
AsyncTask
avait les champs suivants:Dans Android 4.4 (API 19), les champs ci-dessus sont modifiés comme suit:
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.
la source
AsyncTaskCompat.executeParallel(task, params);
AsyncTaskCompat.executeParallel(task, params);
est désormais obsolèteCela permet une exécution parallèle sur toutes les versions d'Android avec API 4+ (Android 1.6+):
Ceci est un résumé de l'excellente réponse d'Arhimed.
Veuillez vous assurer d'utiliser l'API de niveau 11 ou supérieur comme cible de génération de projet. Dans Eclipse, c'est
Project > Properties > Android > Project Build Target
. Cela ne rompra pas la compatibilité descendante avec des niveaux d'API inférieurs. Ne vous inquiétez pas, vous obtiendrez des erreurs Lint si vous utilisez accidentellement des fonctionnalités introduites aprèsminSdkVersion
. Si vous voulez vraiment utiliser les fonctionnalités introduites aprèsminSdkVersion
, vous pouvez supprimer ces erreurs à l'aide d'annotations, mais dans ce cas, vous devez vous soucier de la compatibilité vous-même . C'est exactement ce qui s'est produit dans l'extrait de code ci-dessus.la source
void startMyTask(AsyncTask<Void, ?, ?> asyncTask)
(si votre doInBackground prend Void)Rendre la suggestion @sulai plus générique:
la source
Juste pour inclure la dernière mise à jour (UPDATE 4) dans la réponse immaculée de @Arhimed dans le très bon résumé de @sulai:
la source
.executeOnExecutor()
est désormais redondant pour l'API> = KITKAT, oui?L'exemple des développeurs Android de chargement efficace de bitmaps utilise une tâche asynctrame personnalisée (copiée à partir de jellybean) afin que vous puissiez utiliser le executeOnExecutor dans des API inférieures à <11
http://developer.android.com/training/displaying-bitmaps/index.html
Téléchargez le code et accédez au paquet util.
la source
C'est possible. La version de mon appareil Android est 4.0.4 et android.os.Build.VERSION.SDK_INT est 15
J'ai 3 filateurs
Et j'ai aussi une classe Async-Tack.
Voici mon code de chargement spinner
Cela fonctionne parfaitement. Un à un mes filateurs se chargèrent. Je n'ai pas utilisé executeOnExecutor.
Voici ma classe de tâches Async
la source
si vous souhaitez exécuter des tâches en parallèle, vous devez appeler la méthode
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "your task name")
après la version Android 3.0; mais cette méthode n'existe pas avant Android 3.0 et après 1.6 car elle s'exécute en parallèle par elle-même, donc je vous suggère de personnaliser votre propre classe AsyncTask dans votre projet, pour éviter de lever des exceptions dans différentes versions d'Android.la source