Android AsyncTask fils limites?
Je développe une application où j'ai besoin de mettre à jour certaines informations à chaque fois que l'utilisateur ouvre une session dans le système, j'ai aussi l'utilisation de la base de données dans le téléphone. Pour toutes ces opérations (mises à jour, récupération de données à partir de db et etc.) J'utilise async tâches. Comme jusqu'à présent, je ne vois pas pourquoi je ne devrais pas utiliser, mais récemment j'ai découvert que si je fais un peu d'opérations de certains de mes tâches asynchrones simplement arrêter sur la pré-exécuter et ne sautez pas de doInBackground. C'était juste trop bizarre de le laisser comme ça, alors j'ai mis au point une autre application très simple, juste pour vérifier ce qui est mal. Et assez étrange, j'ai le même comportement lorsque le nombre total de tâches asynchrones atteindre 5, la 6 on s'arrête sur la pré-exécuter.
Ne android ont une limite de asyncTasks sur l'Activité/App? Ou est-ce juste quelque bug et il doit être signalé? Quelqu'un a rencontrer le même problème et peut-être trouvé une solution de contournement pour elle?
Voici le code:
Il suffit de créer 5 de ces threads de travail en arrière-plan:
private class LongAsync extends AsyncTask<String, Void, String>
{
@Override
protected void onPreExecute()
{
Log.d("TestBug","onPreExecute");
isRunning = true;
}
@Override
protected String doInBackground(String... params)
{
Log.d("TestBug","doInBackground");
while (isRunning)
{
}
return null;
}
@Override
protected void onPostExecute(String result)
{
Log.d("TestBug","onPostExecute");
}
}
Et puis créer ce fil. Il entrera preExecute et l'accrocher (il ne sera pas aller à doInBackground).
private class TestBug extends AsyncTask<String, Void, String>
{
@Override
protected void onPreExecute()
{
Log.d("TestBug","onPreExecute");
waiting = new ProgressDialog(TestActivity.this);
waiting.setMessage("Loading data");
waiting.setIndeterminate(true);
waiting.setCancelable(true);
waiting.show();
}
@Override
protected String doInBackground(String... params)
{
Log.d("TestBug","doInBackground");
return null;
}
@Override
protected void onPostExecute(String result)
{
waiting.cancel();
Log.d("TestBug","onPostExecute");
}
}
Vous devez vous connecter pour publier un commentaire.
Tous AsyncTasks sont contrôlés en interne par une commune (statique) ThreadPoolExecutor et un LinkedBlockingQueue. Lorsque vous appelez
execute
sur une AsyncTask, leThreadPoolExecutor
va l'exécuter, quand il est prêt un certain temps dans l'avenir.Le " quand suis-je prêt?' comportement d'un
ThreadPoolExecutor
est contrôlée par deux paramètres, la de base de la taille du pool et la taille maximale du pool. Si il y a moins de noyau taille du pool de threads actuellement actif et un nouveau travail, le liquidateur va créer un nouveau thread et de l'exécuter immédiatement. Si il y a au moins de base de la taille du pool de threads en cours d'exécution, il va essayer de la file d'attente de la poste et attendre jusqu'à ce qu'il y a un thread inactif disponible (c'est à dire jusqu'à ce qu'une tâche est terminée). Si il n'est pas possible de file d'attente de la tâche (la file d'attente peut avoir un max de capacité), il va créer un nouveau thread (jusqu'à maximum la taille du pool de threads) pour l'exécution de travaux dans. Non-core threads inactifs peuvent éventuellement être mis hors service en fonction d'un signal de paramètre de délai d'attente.Avant d'Android 1.6, la base de la taille du pool de 1 et la taille maximale du pool a été de 10. Depuis Android 1.6, la base de la taille du pool est de 5, et la taille maximale du pool est de 128. La taille de la file d'attente est de 10 dans les deux cas. Le keep-alive délai d'attente est de 10 secondes avant 2.3, et 1 seconde depuis.
Avec tout cela à l'esprit, il devient clair pourquoi le
AsyncTask
apparaîtra uniquement pour exécuter 5/6 de vos tâches. La tâche 6 est en cours de mise en file d'attente jusqu'à ce que l'une des autres tâches sont terminées. C'est une très bonne raison pourquoi vous ne devriez pas utiliser AsyncTasks pour des opérations de longue durée - il empêche les autres AsyncTasks de jamais en cours d'exécution.Pour être complet, si vous l'avez répété votre exercice avec plus de 6 tâches (par exemple, 30), vous verrez que plus de 6 entrera
doInBackground
que la file d'attente va être saturé et l'exécuteur testamentaire est poussé à créer plus de threads de travail. Si vous avez gardé tout au long de la tâche en cours d'exécution, vous devriez voir que 20/30 devenir actif, avec 10 encore dans la file d'attente.core pool size
oumaximum pool size
?@antonyt a le droit de réponse, mais dans le cas où vous êtes à la recherche d'une solution simple, puis vous pouvez vérifier l'Aiguille.
Avec elle, vous pouvez définir votre propre taille du pool de threads et, contrairement à
AsyncTask
, il fonctionne sur tous les versions d'Android les mêmes. Avec elle, vous pouvez dire des choses comme:ou des choses comme
Il peut faire encore beaucoup plus. Check it out sur GitHub.
Mise à jour: Depuis API 19 le noyau taille du pool de threads a été modifié afin de refléter le nombre de Processeurs sur le périphérique, avec un minimum de 2 et un maximum de 4 au départ, tandis que la croissance à un max de CPU*2 +1 - Référence
Également noter que, bien que l'exécuteur par défaut de AsyncTask est de série (l'exécution d'une tâche à la fois et dans l'ordre dans lequel ils arrivent), avec la méthode
vous pouvez fournir un Exécuteur testamentaire pour l'exécution de vos tâches. Vous pouvez fournir l'THREAD_POOL_EXECUTOR le sous le capot, un exécuteur testamentaire, mais sans la sérialisation des tâches, ou vous pouvez même créer votre propre Exécuteur testamentaire et de fournir ici.
Toutefois, notez soigneusement l'avertissement de la documentation Javadoc.
Plus qu'une chose à noter est que les deux le cadre Exécuteurs THREAD_POOL_EXECUTOR et sa version de série SERIAL_EXECUTOR (qui est par défaut pour AsyncTask) sont statiques (niveau de la classe de constructions) et donc partagés entre toutes les instances de AsyncTask(s) dans votre application de processus.