Les threads AsyncTask ne meurent jamais

112

J'utilise AsyncTasks pour récupérer des données en réponse à l'utilisateur qui appuie sur un bouton. Cela fonctionne bien et maintient l'interface réactive lors de la récupération des données, mais lorsque j'ai vérifié ce qui se passait dans le débogueur Eclipse, j'ai découvert qu'à chaque fois qu'un nouveau AsyncTaskétait créé (ce qui est assez souvent, car ils ne peuvent être utilisés qu'une seule fois) ), un nouveau thread était en cours de création mais ne s'est jamais terminé.

Le résultat est un grand nombre de AsyncTaskthreads assis juste là. Je ne sais pas si c'est un problème dans la pratique ou non, mais j'aimerais vraiment me débarrasser de ces fils supplémentaires.

Comment puis-je tuer ces fils?

Informatisé
la source
Que voulez-vous dire par "jamais terminé"? La tâche ne termine-t-elle jamais sa méthode doInbackground ou voyez-vous simplement l'objet asynctask dans le traker d'allocation?
Francesco Laurita
7
La doInBackgroundméthode se termine, mais le thread continue à apparaître dans la fenêtre de débogage. Par exemple: Thread [<23> AsyncTask #4](Running)
Informatisé

Réponses:

202

AsyncTaskgère un pool de threads, créé avec ThreadPoolExecutor. Il aura de 5 à 128 threads. S'il y a plus de 5 fils, ces fils supplémentaires resteront autour pendant au plus 10 secondes avant d'être supprimés. (Remarque: ces chiffres concernent le code open source actuellement visible et varient selon la version d'Android).

Laissez les AsyncTaskfils tranquilles, s'il vous plaît.

CommonsWare
la source
Merci pour l'explication! Je suis content de savoir que je ne fais rien de mal. Par curiosité, pourquoi est-il conçu comme ça? Pourquoi ne pas simplement terminer les threads après le retour de toutes les méthodes?
Informatisé
7
Vraisemblablement pour gagner du temps en forçant les threads sur les demandes ultérieures.
CommonsWare
@CommonsWare j'ai un service dans lequel j'exécute une AsyncTask pour effectuer une opération et le service démarre lorsque le bouton du widget est enfoncé et lorsque la tâche est terminée, il doit arrêter le service immédiatement, mais parfois AsyncTask ne mourra pas, vous pouvez donc dis-moi comment puis-je l'arrêter
Chasse
1
@SreekanthKarumanaghat: Utiliser un AsyncTaskpour quelque chose qui prendrait autant de temps est une mauvaise idée en général. Mais non, mon commentaire sur la disparition des fils supplémentaires concerne le moment où ils ne sont pas utilisés. Ainsi, quand l'une de vos 6 tâches se termine, son thread restera dans le pool pendant 10 secondes, après quoi ce thread sera terminé.
CommonsWare
1
@SreekanthKarumanaghat: "Ma question est de savoir s'il existe une restriction pour l'exécution de 20 (disons) AsyncTasks en parallèle?" - utiliser de manière significative AsyncTaskaujourd'hui n'est pas un bon plan. Avoir 20+ qui peuvent fonctionner pendant plus de 10 secondes est le genre de chose qui devrait échouer à une révision de code. Si vous créez 20 tâches en succession rapide, seules quelques-unes seront exécutées à la fois et le reste sera mis en file d'attente pour une exécution ultérieure. Le nombre d'exécutions simultanées dépend du nombre de cœurs du processeur. AFAIK, l'algorithme actuel est 2N + 1 threads parallèles, où N est le nombre de cœurs.
CommonsWare
24

En plus de la réponse de CommonsWare:

Actuellement, j'utilise Android 2.2 et mon application n'utilise pas plus d'une AsyncTask à la fois, mais j'en crée une nouvelle toutes les x minutes. Au début, de nouveaux threads AsyncTask commencent à apparaître (un nouveau thread pour un nouvel AsyncTask) mais après 5 threads (comme mentionné par CommonsWare), ils restent simplement visibles dans la fenêtre de débogage et sont réutilisés lorsque de nouveaux threads AsyncTask sont nécessaires. Ils restent simplement là jusqu'à ce que le débogueur se déconnecte.

Tom de Waard
la source
2
Oui, confirmé: je ne vois pas plus de 5 AsyncTasks.
Seraphim's
3

Même symptôme ici. Dans mon cas, les fils ont traîné après avoir tué l'activité et j'espérais que l'application se ferme complètement. Problème partiellement résolu en utilisant un seul exécuteur threadé:

    myActiveTask.executeOnExecutor(Executors.newSingleThreadExecutor());

Cela a fait disparaître le fil une fois son travail terminé.

Karnbo
la source
Cette réponse a fait disparaître la tâche AsyncTask après son exécution, peut-être que ce n'est pas la "manière google de faire les choses", mais elle fait le travail. Je vous remercie.
Henrique de Sousa
Cela a résolu mon problème spécifique concernant l'exécution d'Asynctasks sur un seul thread.
Law Gimenez
0

Utilisez ThreadPoolExecutor .

BlockingQueue workQueue= new LinkedBlockingQueue<Runnable>(100); // Work pool size
ThreadPoolExecutor executor = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors(),       // Initial pool size
            Runtime.getRuntime().availableProcessors(),       // Max pool size
            1, // KEEP_ALIVE_TIME
            TimeUnit.SECONDS, //  KEEP_ALIVE_TIME_UNIT
            workQueue);

Publiez votre Runnabletâche en utilisant la méthode execute () .

void execute (Runnable command)

Exécute la tâche donnée ultérieurement. La tâche peut s'exécuter dans un nouveau thread ou dans un thread poolé existant

Concernant votre deuxième requête:

Comment puis-je tuer ces fils?

Une fois que vous avez terminé tout votre travail avec ThreadPoolExecutor, arrêtez-le correctement comme indiqué dans le post ci-dessous:

Comment arrêter correctement Java ExecutorService

Ravindra babu
la source