AsyncTask-Threads sterben nie ab

112

Ich verwende AsyncTasks, um Daten abzurufen, wenn der Benutzer eine Taste drückt. Dies funktioniert gut und sorgt dafür, dass die Benutzeroberfläche beim Abrufen der Daten reagiert. Als ich jedoch überprüfte, was im Eclipse-Debugger vor sich ging, stellte ich fest, dass jedes Mal ein neues AsyncTaskerstellt wurde (was häufig der Fall ist, da sie nur einmal verwendet werden können ) wurde ein neuer Thread erstellt, aber nie beendet.

Das Ergebnis ist eine große Anzahl von AsyncTaskThreads, die gerade dort sitzen. Ich bin mir nicht sicher, ob dies in der Praxis ein Problem ist oder nicht, aber ich würde diese zusätzlichen Threads wirklich gerne loswerden.

Wie kann ich diese Threads beenden?

Computerisch
quelle
Was meinst du mit "nie beendet"? Beendet die Task niemals ihre doInbackground-Methode oder sehen Sie nur das asynctask-Objekt im Allocation-Traker?
Francesco Laurita
7
Die doInBackgroundMethode ist abgeschlossen, aber der Thread wird weiterhin im Debug-Fenster angezeigt. Zum Beispiel: Thread [<23> AsyncTask #4](Running)
Computerish

Antworten:

202

AsyncTaskverwaltet einen Thread-Pool, der mit erstellt wurde ThreadPoolExecutor. Es wird 5 bis 128 Threads haben. Wenn mehr als 5 Fäden vorhanden sind, bleiben diese zusätzlichen Fäden höchstens 10 Sekunden lang bestehen, bevor sie entfernt werden. (Hinweis: Diese Zahlen gelten für den derzeit sichtbaren Open Source-Code und variieren je nach Android-Version.)

Lass die AsyncTaskFäden bitte in Ruhe.

CommonsWare
quelle
Danke für die Erklärung! Ich bin froh zu wissen, dass ich nichts falsch mache. Warum ist es aus Neugier so gestaltet? Warum nicht einfach die Threads beenden, nachdem alle Methoden zurückgekehrt sind?
Computerish
7
Vermutlich, um bei späteren Anfragen Zeit zu sparen.
CommonsWare
@CommonsWare Ich habe einen Dienst, in dem ich eine AsyncTask ausführe, um eine Operation auszuführen, und der Dienst startet, wenn die Widget-Schaltfläche gedrückt wird und wenn die Aufgabe beendet ist, muss der Dienst sofort gestoppt werden, aber manchmal stirbt AsyncTask nicht, also können Sie Sag mir, wie ich es aufhalten kann
Hunt
1
@SreekanthKarumanaghat: Die Verwendung eines AsyncTaskfür etwas, das so lange dauern würde, ist im Allgemeinen eine schlechte Idee. Aber nein, mein Kommentar zu den zusätzlichen Threads, die weggehen, ist, wenn sie nicht verwendet werden. Wenn eine Ihrer 6 Aufgaben beendet ist, bleibt der Thread 10 Sekunden lang im Pool. Danach wird dieser Thread beendet.
CommonsWare
1
@SreekanthKarumanaghat: "Meine Frage ist, ob es eine Einschränkung für die parallele Ausführung von 20 (sagen wir) AsyncTasks gibt." - Die AsyncTaskheutige Nutzung sinnvoll zu nutzen, ist kein guter Plan. 20+, die länger als 10 Sekunden laufen können, sollten eine Codeüberprüfung nicht bestehen. Wenn Sie 20 Aufgaben schnell hintereinander erstellen, werden nur wenige gleichzeitig ausgeführt, und der Rest wird für die spätere Ausführung in die Warteschlange gestellt. Wie viele gleichzeitig ausgeführt werden, hängt von der Anzahl der Kerne der CPU ab. AFAIK, der aktuelle Algorithmus ist 2N + 1 parallele Threads, wobei N die Anzahl der Kerne ist.
CommonsWare
24

Zusätzlich zur Antwort von CommonsWare:

Derzeit verwende ich Android 2.2 und meine Anwendung verwendet zu keinem Zeitpunkt mehr als eine AsyncTask, aber ich erstelle alle x Minuten eine neue. Zuerst werden neue AsyncTask-Threads angezeigt (ein neuer Thread für eine neue AsyncTask), aber nach 5 Threads (wie von CommonsWare erwähnt) bleiben sie nur im Debug-Fenster sichtbar und werden wiederverwendet, wenn neue AsyncTask-Threads benötigt werden. Sie bleiben einfach dort, bis der Debugger die Verbindung trennt.

Tom de Waard
quelle
2
Ja, bestätigt: Ich sehe nicht mehr als 5 AsyncTasks.
Seraphims
3

Gleiches Symptom hier. In meinem Fall hingen die Threads herum, nachdem ich die Aktivität beendet hatte, und ich hoffte, dass die App vollständig geschlossen wurde. Problem teilweise gelöst mit einem einzelnen Thread-Executor:

    myActiveTask.executeOnExecutor(Executors.newSingleThreadExecutor());

Dies ließ den Faden nach Abschluss seiner Arbeit verschwinden.

Karnbo
quelle
Diese Antwort hat dazu geführt, dass die AsyncTask nach dem Ausführen nicht mehr funktioniert. Vielleicht ist es nicht die "Google-Methode", aber sie erledigt den Job. Danke dir.
Henrique de Sousa
Dies löste mein spezifisches Problem beim Ausführen von Asynctasks auf einem einzelnen Thread.
Gesetz Gimenez
0

Verwenden Sie 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);

Veröffentlichen Sie Ihre RunnableAufgabe mit der Methode execute () .

void execute (Runnable command)

Führt die angegebene Aufgabe irgendwann in der Zukunft aus. Die Aufgabe kann in einem neuen Thread oder in einem vorhandenen gepoolten Thread ausgeführt werden

Zu Ihrer zweiten Anfrage:

Wie kann ich diese Threads beenden?

Wenn Sie mit all Ihrer Arbeit fertig sind, fahren Sie ThreadPoolExecutorsie ordnungsgemäß herunter, wie im folgenden Beitrag angegeben:

So beenden Sie Java ExecutorService ordnungsgemäß

Ravindra Babu
quelle