Los subprocesos de AsyncTask nunca mueren


112

Estoy usando AsyncTasks para obtener datos en respuesta a que el usuario presione un botón. Esto funciona bien y mantiene la interfaz receptiva mientras se obtienen los datos, pero cuando verifiqué lo que estaba sucediendo en el depurador de Eclipse, descubrí que cada vez que AsyncTaskse creaba uno nuevo (lo cual es bastante frecuente, porque solo se pueden usar una vez ), se estaba creando un nuevo hilo pero nunca se terminó.

El resultado es una gran cantidad de AsyncTaskhilos ahí. No estoy seguro de si esto es un problema en la práctica o no, pero realmente me gustaría deshacerme de esos hilos adicionales.

¿Cómo puedo matar estos hilos?


¿Qué quieres decir con "nunca terminado"? ¿La tarea nunca finaliza su método doInbackground o simplemente ve el objeto asynctask en el rastreador de asignación?
Francesco Laurita

7
El doInBackgroundmétodo se completa, pero el hilo continúa apareciendo en la ventana de depuración. Por ejemplo: Thread [<23> AsyncTask #4](Running)
Computerish

Respuestas:


202

AsyncTaskadministra un grupo de subprocesos, creado con ThreadPoolExecutor. Tendrá de 5 a 128 hilos. Si hay más de 5 hilos, esos hilos adicionales se mantendrán durante un máximo de 10 segundos antes de ser eliminados. (nota: estas cifras son para el código fuente abierto actualmente visible y varían según la versión de Android).

Deje los AsyncTaskhilos en paz, por favor.


¡Gracias por la explicación! Me alegra saber que no estoy haciendo nada malo. Por curiosidad, ¿por qué está diseñado así? ¿Por qué no terminar los hilos después de que todos los métodos hayan regresado?
Computerish

7
Presumiblemente para ahorrar tiempo al bifurcar los hilos en solicitudes posteriores.
CommonsWare

@CommonsWare tengo un servicio en el que estoy ejecutando una AsyncTask para realizar alguna operación y el servicio se inicia cuando se presiona el botón del widget y cuando la tarea finaliza debe detener el servicio inmediatamente, pero a veces AsyncTask no muere, tú también puedes dime cómo lo detengo
Hunt

1
@SreekanthKarumanaghat: Usar un AsyncTaskpara algo que tomaría tanto tiempo es una mala idea en general. Pero no, mi comentario sobre la desaparición de hilos adicionales es cuando no se utilizan. Entonces, cuando una de sus 6 tareas finaliza, su hilo permanecerá en el grupo durante 10 segundos, después de lo cual ese hilo terminará.
CommonsWare

1
@SreekanthKarumanaghat: "Mi pregunta es si hay alguna restricción para ejecutar 20 (digamos) AsyncTasks en paralelo?" - Hacer un uso significativo de la AsyncTaskactualidad no es un gran plan. Tener más de 20 que pueden durar más de 10 segundos es el tipo de cosas que deberían fallar en una revisión de código. Si crea 20 tareas en rápida sucesión, solo unas pocas se ejecutarán a la vez y el resto se pondrá en cola para su ejecución posterior. La cantidad que se ejecutará a la vez se basa en la cantidad de núcleos de la CPU. AFAIK, el algoritmo actual es 2N + 1 hilos paralelos, donde N es el número de núcleos.
CommonsWare

24

Además de la respuesta de CommonsWare:

Actualmente estoy usando Android 2.2 y mi aplicación no usa más de una AsyncTask a la vez, pero estoy creando una nueva cada x minutos. Al principio, comienzan a aparecer nuevos subprocesos AsyncTask (un nuevo subproceso para un nuevo AsyncTask) pero después de 5 subprocesos (como lo menciona CommonsWare) simplemente permanecen visibles en la ventana de depuración y se reutilizan cuando se necesitan nuevos subprocesos AsyncTask. Simplemente permanecen allí hasta que el depurador se desconecta.


2
Sí, confirmado: no veo más de 5 AsyncTasks.
Seraphim's

3

El mismo síntoma aquí. En mi caso, los hilos quedaron colgados después de que maté la actividad, y esperaba que la aplicación se cerrara por completo. Problema parcialmente resuelto mediante el uso de un ejecutor de un solo hilo:

    myActiveTask.executeOnExecutor(Executors.newSingleThreadExecutor());

Esto hizo que el hilo se desvaneciera después de completar su trabajo.


Esta respuesta hizo que AsyncTask desapareciera después de su ejecución, tal vez no sea la "forma de hacer las cosas de Google", pero hace el trabajo. Gracias.
Henrique de Sousa

Esto resolvió mi problema específico con respecto a la ejecución de Asynctasks en un solo hilo.
Law Gimenez

0

Utilice 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 su Runnabletarea utilizando el método execute () .

void execute (Runnable command)

Ejecuta la tarea dada en algún momento en el futuro. La tarea puede ejecutarse en un hilo nuevo o en un hilo agrupado existente

Respecto a su segunda consulta:

¿Cómo puedo matar estos hilos?

Una vez que haya terminado con todo su trabajo con ThreadPoolExecutor , apáguelo correctamente como se cita en la siguiente publicación:

Cómo apagar correctamente Java ExecutorService

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.