2010-07-13 16 views
9

Tengo una aplicación Java que no termina. El método principal finaliza, pero los hilos permanecen activos y la aplicación no finaliza. El caso es que no parece haber ningún bloqueo/espera de monitor, por lo que no veo por qué no termina. Según Eclipse, me quedan dos hilos no Daemon. Uno está etiquetado [DestroyJavaVM] (parece esperanzador) y el otro parece estar bloqueado en Unsafe.park(boolean, long). ¿Cómo/dónde debería comenzar a investigar esto?¿Por dónde empiezo a investigar mi proceso de Java que no terminará?

El StackTrace abreviada del segundo hilo es:

Unsafe.park(boolean, long) 
at LockSupport.park(Object) 
at AbstractQueuedSynchronizer$ConditionObject.await() 
at LinkedBlockingQueue<E>.take() 
at ThreadPoolExecutor.getTask() 
at ThreadPoolExecutor$Worker.run() 
at Thread.run() 
+0

¿Cuál es el seguimiento de la pila completa del hilo en Unsafe.park()? –

+0

Unsafe.park (booleano, largo) -> LockSupport.park (Object) -> AbstractQueuedSynchronizer $ ConditionObject.await() -> LinkedBlockingQueue .take() -> ThreadPoolExecutor.getTask() -> ThreadPoolExecutor $ Worker.run() -> Hilo.run() – JenFallow

+0

He editado su comentario en la pregunta porque es mucho más fácil de leer en un bloque de código, y porque forma una parte importante de la pregunta en sí. –

Respuesta

0

vertederos hilo y depuradores sería mi conjetura.

0

No estoy seguro de qué tan grande es la aplicación, pero verificaría todos los subprocesos que ha creado y me aseguraré de que sus métodos de ejecución se eliminen limpiamente cuando la aplicación termine de ejecutarse. En algún lugar, dentro de un hilo, es posible que tenga código a lo largo de las líneas de:

public void run() { 
    while(true) { //"true" or some condition that never gets a chance to be false 
     //do thread related work 
    } 
} 
0

Unsafe.park, a pesar del nombre que suena aterrador, se suele utilizar por todo tipo de bloqueo de llamadas (especialmente aquellos en el nuevo (ISH) java.util.concurrent paquete).

Si nos fijamos una serie de imágenes más abajo en la pila, te gusta ver algo como java.util.concurrent.LinkedBlockingQueue.take (es decir, alguna clase de biblioteca JDK), seguido de algo así como com.example.myapp.MyClass.getNextJob (es decir, la clase que está utilizando la biblioteca de clases).

Si tuviera que aventurar una suposición, diría que está haciendo una especie de llamada que bloquea para siempre, así que cuando no hay nada más que devolver, este hilo simplemente se queda allí esperando el "siguiente" elemento . Podrías resolver esto estableciendo algún tipo de indicador de "finalización", y luego interrumpir el hilo de espera o dar un tiempo de espera a la llamada de bloqueo, haciendo que compruebe el indicador. Dependiendo de su código, cualquiera de estos o una alternativa podría ser factible, pero espero que esto sea suficiente para comenzar.

Editar: después de ver el stacktrace, finnw is right que necesita para apagar su servicio ejecutor.

1

que tiene que hacer una de dos cosas a finalizar su ExecutorService discusión: (. La clase ThreadFactoryBuilder de Guava hará que esto sea más fácil)

  1. Especifique un ThreadFactory que crea hilos demonio
  2. llamada shutdown() en su ExecutorService como parte del cierre de la aplicación (por ejemplo, al final de su método de main.)
+0

+1: 'shutdown()' es la manera canónica de hacerlo: los subprocesos de daemon evitarían este problema, pero es muy posible que no sean los deseados y * podrían * dar lugar a problemas más adelante. –

0

su tarea es bloqueado esperando datos de la cola. Take no tiene un tiempo de espera asociado.

Mantenga una referencia a la secuencia de tareas cuando se crea. En el cierre, llame al método de interrupción en el hilo. También es posible que necesite modificar el ciclo de procesamiento de trabajo que las llamadas toman para salir cuando se detecta la excepción InterruptedException.

Cuestiones relacionadas