I thread AsyncTask non muoiono mai


112

Sto usando AsyncTasks per recuperare i dati in risposta all'utente che preme un pulsante. Funziona bene e mantiene l'interfaccia reattiva durante il recupero dei dati, ma quando ho controllato cosa stava succedendo nel debugger di Eclipse, ho scoperto che ogni volta che ne AsyncTaskveniva creato un nuovo (che è abbastanza spesso, perché possono essere usati solo una volta ), è stato creato un nuovo thread ma non è mai stato terminato.

Il risultato è un gran numero di AsyncTaskthread semplicemente seduti lì. Non sono sicuro se questo sia un problema in pratica o meno, ma mi piacerebbe davvero sbarazzarmi di quei thread extra.

Come posso eliminare questi thread?


Cosa intendi con "mai terminato"? L'attività non termina mai il suo metodo doInbackground o vedi solo l'oggetto asynctask nel traker di allocazione?
Francesco Laurita

7
Il doInBackgroundmetodo viene completato, ma il thread continua a essere visualizzato nella finestra di debug. Ad esempio: Thread [<23> AsyncTask #4](Running)
Computerish

Risposte:


202

AsyncTaskgestisce un pool di thread, creato con ThreadPoolExecutor. Avrà da 5 a 128 thread. Se ci sono più di 5 thread, quei thread extra rimarranno in giro per un massimo di 10 secondi prima di essere rimossi. (nota: queste cifre si riferiscono al codice open source attualmente visibile e variano in base alla versione di Android).

Lascia stare i AsyncTaskfili, per favore.


Grazie per la spiegazione! Sono contento di sapere che non sto facendo niente di sbagliato. Per curiosità, perché è progettato così? Perché non terminare i thread solo dopo che tutti i metodi sono stati restituiti?
Computerish

7
Presumibilmente per risparmiare tempo nel forkare i thread su richieste successive.
CommonsWare

@CommonsWare ho un servizio in cui sto eseguendo un AsyncTask per eseguire alcune operazioni e il servizio si avvia quando viene premuto il pulsante del widget e quando l'attività è terminata deve interrompere immediatamente il servizio, ma a volte AsyncTask non muore, quindi puoi dimmi come faccio a fermarlo
Caccia

1
@SreekanthKarumanaghat: Usare un AsyncTaskper qualcosa che richiederebbe così tanto tempo è una cattiva idea in generale. Ma no, il mio commento sui thread in più che scompaiono è quando non vengono utilizzati. Quindi, quando una delle tue 6 attività termina, il suo thread rimarrà nel pool per 10 secondi, dopodiché quel thread verrà terminato.
CommonsWare

1
@SreekanthKarumanaghat: "La mia domanda è se ci sono limitazioni per l'esecuzione di 20 (diciamo) AsyncTasks in Parallel?" - fare un uso significativo di AsyncTaskoggi non è un grande piano. Avere più di 20 che possono essere eseguiti per più di 10 secondi è il genere di cose che dovrebbero fallire una revisione del codice. Se crei 20 attività in rapida successione, solo alcune verranno eseguite contemporaneamente e le altre verranno messe in coda per l'esecuzione successiva. Quanti verranno eseguiti contemporaneamente si basa sul numero di core della CPU. Per quanto ne so, l'algoritmo corrente è 2N + 1 thread paralleli, dove N è il numero di core.
CommonsWare

24

Oltre alla risposta di CommonsWare:

Attualmente sto utilizzando Android 2.2 e la mia applicazione non utilizza più di un AsyncTask alla volta, ma ne sto creando uno nuovo ogni x minuti. All'inizio iniziano a comparire nuovi thread AsyncTask (un nuovo thread per un nuovo AsyncTask) ma dopo 5 thread (come menzionato da CommonsWare) rimangono visibili nella finestra di debug e vengono riutilizzati quando sono necessari nuovi thread AsyncTask. Rimangono lì finché il debugger non si disconnette.


2
Sì, confermato: non vedo più di 5 AsyncTask.
Seraphim il

3

Stesso sintomo qui. Nel mio caso i thread si sono bloccati dopo aver terminato l'attività e speravo che l'app si chiudesse completamente. Problema parzialmente risolto utilizzando un unico esecutore a thread:

    myActiveTask.executeOnExecutor(Executors.newSingleThreadExecutor());

Questo ha fatto svanire il filo dopo aver completato il suo lavoro.


Questa risposta ha fatto sparire l'AsyncTask dopo che è stato eseguito, forse non è il "modo di fare cose di Google" ma fa il lavoro. Grazie.
Henrique de Sousa

Questo ha risolto il mio problema specifico riguardante l'esecuzione di Asynctask su un singolo thread.
Legge Gimenez

0

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

Pubblica la tua Runnableattività utilizzando il metodo execute () .

void execute (Runnable command)

Esegue l'attività data in futuro. L'attività può essere eseguita in un nuovo thread o in un thread in pool esistente

Per quanto riguarda la tua seconda query:

Come posso eliminare questi thread?

Una volta che hai finito con tutto il tuo lavoro ThreadPoolExecutor, spegnilo correttamente come citato nel post sottostante:

Come chiudere correttamente java ExecutorService

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.