hilos ejemplo java multithreading tomcat6 executorservice

ejemplo - java concurrency



¿Desactivar el servicio del ejecutor con gracia en la aplicación web? (2)

En mi aplicación web, creé un servicio que utiliza un ExecutorService con un tamaño fijo de ThreadPool. Reutilizo el mismo ExecutorService durante toda la vida de la aplicación.

private static ExecutorService pool = Executors.newFixedThreadPool(8);

Todo se ejecuta en Tomcat, lo que me da el siguiente error al apagar:

appears to have started a thread named [pool-1-thread-1] but has failed to stop it. This is very likely to create a memory leak.

Me doy cuenta de que necesito apagar el ExecutorService antes de apagar Tomcat. El hilo de Soms SO ya habla sobre esto, pero no pude encontrar una manera limpia de manejar esto.

¿Debo usar un ShutdownHook como se sugiere en @ Tim-bender en Graceful shutdown of threads and executor ? ¿O debería usar un CachedThreadPool en su lugar?


Además de lo que Tomasz sugirió que también puedes usar CachedThreadPool

Los hilos que no se han utilizado durante sesenta segundos se terminan y se eliminan de la memoria caché. Por lo tanto, un grupo que permanece inactivo durante el tiempo suficiente no consumirá ningún recurso.

Entonces, una muy buena solución sería usar CachedThreadPool y apagarlo en ServletContextListener.contextDestroyed() .


El gancho de apagado no es un buen enfoque en Tomcat porque:

  • cerrará la piscina demasiado tarde (al cerrarse), Tomcat ya le avisará sobre los recursos que no están cerrados

  • realmente desea cerrar ese grupo cuando la aplicación no está desplegada, de modo que la redistribución funcione (de lo contrario, cada aplicación creará un nuevo grupo y se cerrarán solo después de un cierre completo)

  • apagar el grupo de subprocesos puede llevar algún tiempo (ver más abajo), el gancho de apagado debe ser lo más rápido posible

Un lugar mucho mejor es ServletContextListener.contextDestroyed() . Recuerde que debe tanto shutdownNow() el grupo (para cancelar la ejecución y rechazar nuevas tareas) como awaitTermination() para esperar a que las tareas en ejecución finalicen y todas las hebras se detengan.