thread isterminated ejemplo awaittermination java android executorservice

java - isterminated - Motivo del apagado de la llamada() en ExecutorService



java executorservice thread pool (4)

Estuve leyendo sobre ello bastante en las últimas dos horas, y simplemente no puedo ver ningún motivo (razón válida) para llamar a shutdown() en el ExecutorService , a menos que tengamos una aplicación enorme que almacene docenas y docenas de diferentes servicios de ejecutor que no se usan durante mucho tiempo.

Lo único (por lo que veo) que el cierre sí lo es, es hacer lo que hace un hilo normal una vez que lo hace. Cuando el Thread normal termine el método de ejecución de Runnable (o Callable), se pasará a Garbage Collection para que se recopile. Con Executor Service, los hilos simplemente se pondrán en espera, no se marcarán para la recolección de basura. Para eso, el cierre es necesario.

Ok, de vuelta a mi pregunta. ¿Hay alguna razón para solicitar el cierre de ExecutorService mucha frecuencia o incluso después de enviar algunas tareas? Me gustaría dejar atrás el caso de que alguien lo está haciendo y justo después de eso llama a awaitTermination() ya que esto está validado. Una vez que hacemos eso, tenemos que volver a crear un nuevo ExecutorService para hacer lo mismo. ¿No es toda la idea de ExecutorService reutilizar los hilos? Entonces, ¿por qué destruir el ExecutorService tan pronto?

¿No es una forma racional simplemente crear ExecutorService (o pareja dependiendo de cuántos necesita), y luego durante la ejecución de la aplicación, pasarles las tareas una vez que aparecen, y luego al salir de la aplicación o cerrar otras etapas importantes, ejecutores?

Me gustaría recibir respuestas de algunos programadores experimentados que escriben una gran cantidad de código asincrónico utilizando ExecutorServices.

Segunda pregunta lateral, un poco más pequeño trata con la plataforma de Android. SI algunos de ustedes dirán que no es la mejor idea apagar los ejecutores todo el tiempo, y programar en Android, ¿podrían decirme cómo manejan esos cierres (para ser específicos, cuando los ejecutan) cuando tratamos con diferentes eventos de ciclo de vida de la aplicación.

Debido al comentario de CommonsWare, hice el post neutral. Realmente no estoy interesado en discutir sobre ello hasta la muerte y parece que está liderando allí. Solo estoy interesado en conocer lo que les pedí a los desarrolladores experimentados, si están dispuestos a compartir sus experiencias. Gracias.


¿No es toda la idea de ExecutorService reutilizar los hilos? Entonces, ¿por qué destruir el ExecutorService tan pronto?

Sí. No debe destruir y volver a crear ExecutorService frecuencia. Inicialice ExecutorService cuando lo requiera (principalmente al inicio) y manténgalo activo hasta que haya terminado con él.

¿No es una forma racional simplemente crear ExecutorService (o pareja dependiendo de cuántos necesita), y luego durante la ejecución de la aplicación, pasarles las tareas una vez que aparecen, y luego al salir de la aplicación o cerrar otras etapas importantes, ejecutores?

Sí. Es racional cerrar ExecutorService en etapas importantes como la salida de la aplicación, etc.

Segunda pregunta lateral, un poco más pequeño trata con la plataforma de Android. Si algunos de ustedes dicen que no es la mejor idea cerrar los ejecutores cada vez, y programar en Android, ¿podrían decirme cómo manejan esos cierres (para ser específicos, cuando los ejecutan) cuando tratamos con diferentes eventos de aplicación? ciclo vital.

Suponga que ExecutorService se comparte en diferentes actividades en su aplicación. Cada actividad se pausará / reanudará en diferentes intervalos de tiempo y todavía necesita un ExecutorService por su aplicación.

En lugar de administrar el estado de ExecutorService en los métodos del ciclo de vida de la actividad, mueva la administración ExecutorService (Creación / Apagado) a su Service personalizado.

Crear ExecutorService en Service => onCreate() y onDestroy() correctamente en onDestroy()

Forma recomendada de cerrar ExecutorService :

Cómo cerrar correctamente el ExecutorService de Java


Un ExecutorService debería cerrarse una vez que ya no sea necesario para liberar recursos del sistema y permitir el apagado ordenado de la aplicación. Como los subprocesos de un ExecutorService pueden ser subprocesos no de demonio, pueden impedir la finalización normal de la aplicación. En otras palabras, su aplicación sigue ejecutándose después de completar su método principal.

Libro de referencia

Chaper: 14 Página: 814


El método shutdown() hace una cosa: evita que los clientes envíen más trabajo al servicio del ejecutor. Esto significa que todas las tareas existentes seguirán ejecutándose hasta que se tomen otras medidas. Esto es cierto incluso para tareas programadas, por ejemplo, para un ScheduledExecutorService: las nuevas instancias de la tarea programada no se ejecutarán. Esto puede ser útil en varios escenarios.

Supongamos que tiene una aplicación de consola que tiene un servicio de ejecutor ejecutando N tareas. Si el usuario pulsa CTRL-C, espera que la aplicación finalice, posiblemente con elegancia. ¿Qué significa graciosamente? Quizás desee que su aplicación no pueda enviar más tareas al servicio del ejecutor y al mismo tiempo desea esperar a que se completen sus tareas N existentes. Puede lograr esto usando un gancho de cierre como último recurso:

final ExecutorService service = ... // get it somewhere Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { System.out.println("Performing some shutdown cleanup..."); service.shutdown(); while (true) { try { System.out.println("Waiting for the service to terminate..."); if (service.awaitTermination(5, TimeUnit.SECONDS)) { break; } } catch (InterruptedException e) { } } System.out.println("Done cleaning"); } }));

Este enlace cerrará el servicio, lo que evitará que su aplicación envíe nuevas tareas, y esperará a que se completen todas las tareas existentes antes de apagar la JVM. La terminación a la espera se bloqueará durante 5 segundos y se devolverá verdadera si el servicio está apagado. Esto se realiza en un bucle para asegurarse de que el servicio se cerrará eventualmente. La InterruptedException se traga cada vez. Esta es la mejor manera de cerrar un servicio de ejecutor que se reutiliza en toda la aplicación.

Este código no es perfecto. A menos que esté absolutamente seguro de que sus tareas terminarán eventualmente, es posible que desee esperar un tiempo de espera determinado y luego simplemente salir, abandonando los hilos en ejecución. En este caso, tendría sentido llamar también a shutdownNow() después del tiempo de espera en un intento final de interrumpir los hilos en ejecución ( shutdownNow() también le dará una lista de tareas esperando para ejecutarse). Si sus tareas están diseñadas para responder a la interrupción, esto funcionará bien.

Otro escenario interesante es cuando tiene un ScheduledExecutorService que realiza una tarea periódica. La única manera de detener la cadena de tareas periódicas es llamar a shutdown() .

EDITAR: Me gustaría añadir que no recomendaría usar un gancho de apagado como se muestra arriba en el caso general: puede ser propenso a errores y debe ser solo un último recurso. Además, si tiene muchos ganchos de apagado registrados, el orden en que se ejecutarán no está definido, lo que podría no ser conveniente. Prefiero que la aplicación llame explícitamente a shutdown() en InterruptedException .


Motivo del apagado de la llamada () en ExecutorService

Hoy encontré una situación en la que tengo que esperar hasta que una máquina esté lista, antes de comenzar una serie de tareas en esa máquina.

Hago una llamada REST a esta máquina, si no recibo 503 (Servidor no disponible), entonces la máquina está lista para procesar mis solicitudes. Por lo tanto, espero hasta obtener 200 (éxito) para la primera llamada REST.

Hay múltiples formas de lograrlo, utilicé ExecutorService para crear un hilo y lo programé para que se ejecutara después de cada X Segundos. Entonces, necesito detener este hilo en una condición, mira esto ...

final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); Runnable task = () -> { try { int statusCode = restHelper.firstRESTCall(); if (statusCode == 200) { executor.shutdown(); } } catch (Exception e) { e.printStackTrace(); } }; int retryAfter = 60; executor.scheduleAtFixedRate(task, 0, retryAfter, TimeUnit.SECONDS);

Segunda pregunta lateral, un poco más pequeño trata con la plataforma de Android.

¡Tal vez pueda responder si me proporcionas un poco más de contexto! También por mi experiencia con el desarrollo de Android, rara vez necesitas hilos. ¿Estás desarrollando un juego o una aplicación que necesita hilos para el rendimiento? Si no, en Android tiene otras formas de abordar problemas como el escenario que expliqué anteriormente. Puede usar TimerTask, AsyncTask o Handlers o Loaders en función del contexto. Esto es porque si UIThread espera por mucho tiempo, sabes lo que sucede: /