Threads AsyncTask nunca morrem


112

Estou usando AsyncTasks para buscar dados em resposta ao usuário pressionando um botão. Isso funciona bem e mantém a interface responsiva enquanto busca os dados, mas quando eu verifiquei o que estava acontecendo no depurador Eclipse, descobri que toda vez que um novo AsyncTaskera criado (o que é muito frequente, porque eles só podem ser usados ​​uma vez ), um novo encadeamento estava sendo criado, mas nunca encerrado.

O resultado é um grande número de AsyncTasktópicos parados ali. Não tenho certeza se isso é um problema na prática ou não, mas eu realmente gostaria de me livrar desses tópicos extras.

Como posso matar esses tópicos?


O que você quer dizer com "nunca encerrado"? A tarefa nunca termina seu método doInbackground ou você apenas vê o objeto asynctask no rastreador de alocação?
Francesco Laurita

7
O doInBackgroundmétodo é concluído, mas o encadeamento continua a aparecer na janela de depuração. Por exemplo: Thread [<23> AsyncTask #4](Running)
Informatizado de

Respostas:


202

AsyncTaskgerencia um pool de threads, criado com ThreadPoolExecutor. Terá de 5 a 128 threads. Se houver mais de 5 threads, esses threads extras permanecerão por no máximo 10 segundos antes de serem removidos. (nota: esses números são para o código-fonte aberto visível no momento e variam de acordo com a versão do Android).

Deixe os AsyncTasktópicos em paz, por favor.


Obrigada pelo esclarecimento! Fico feliz em saber que não estou fazendo nada de errado. Por curiosidade, por que foi projetado assim? Por que não apenas encerrar os threads depois que todos os métodos forem retornados?
Computadorizado de

7
Presumivelmente, para economizar tempo bifurcando os threads em solicitações posteriores.
CommonsWare

@CommonsWare eu tenho um serviço no qual estou executando uma AsyncTask para realizar alguma operação e o serviço começa quando o botão do widget está sendo pressionado e quando a tarefa é concluída, ele deve parar o serviço imediatamente, mas às vezes AsyncTask não morre, então você pode diga-me como faço para pará-lo
Hunt

1
@SreekanthKarumanaghat: Usar um AsyncTaskpara algo que demoraria tanto é uma má ideia em geral. Mas não, meu comentário sobre os tópicos extras indo embora é quando eles não são usados. Portanto, quando uma de suas 6 tarefas terminar, seu encadeamento permanecerá no pool por 10 segundos, após os quais o encadeamento será encerrado.
CommonsWare

1
@SreekanthKarumanaghat: "Minha pergunta é se há alguma restrição para executar 20 (digamos) AsyncTasks em paralelo?" - fazer uso significativo do AsyncTaskhoje não é um grande plano. Ter mais de 20 que podem ser executados por mais de 10 segundos é o tipo de coisa que deve falhar em uma revisão de código. Se você criar 20 tarefas em rápida sucessão, apenas algumas serão executadas de uma vez e o restante será enfileirado para execução posterior. Quantos serão executados de uma vez é baseado no número de núcleos da CPU. AFAIK, o algoritmo atual é 2N + 1 threads paralelos, onde N é o número de núcleos.
CommonsWare de

24

Além da resposta do CommonsWare:

Atualmente estou usando o Android 2.2 e meu aplicativo não usa mais do que uma AsyncTask por vez, mas estou criando uma nova a cada x minutos. No início, novos Threads AsyncTask começam a aparecer (um novo Thread para uma nova AsyncTask), mas após 5 threads (como mencionado por CommonsWare), eles apenas permanecem visíveis na janela de depuração e são reutilizados quando novos threads AsyncTask são necessários. Eles apenas ficam lá até que o depurador seja desconectado.


2
Sim, confirmado: não vejo mais do que 5 AsyncTasks.
Serafim de

3

Mesmo sintoma aqui. No meu caso, os tópicos ficaram pendurados depois que eu encerrei a Activity, e eu esperava que o App fechasse completamente. Problema parcialmente resolvido usando um único executor encadeado:

    myActiveTask.executeOnExecutor(Executors.newSingleThreadExecutor());

Isso fez com que o tópico desaparecesse após a conclusão de seu trabalho.


Esta resposta fez o AsyncTask desaparecer depois de ser executado, talvez não seja o "jeito google de fazer as coisas", mas dá conta do recado. Obrigado.
Henrique de Sousa

Isso resolveu meu problema específico em relação à execução de Asynctasks em um único thread.
Law Gimenez

0

Use 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);

Publique sua Runnabletarefa usando o método execute () .

void execute (Runnable command)

Executa a tarefa fornecida em algum momento no futuro. A tarefa pode ser executada em uma nova thread ou em uma thread em pool existente

Em relação à sua segunda consulta:

Como posso matar esses tópicos?

Assim que tiver concluído todo o seu trabalho ThreadPoolExecutor, desligue-o adequadamente conforme citado na postagem abaixo:

Como desligar corretamente o java ExecutorService

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.