2011-11-04 18 views
6

De acuerdo con javadoc, si llamo a receive() en javax.jms.MessageConsumer, se bloqueará indefinidamente hasta que se produzca un mensaje o hasta que se cierre el consumidor del mensaje.javax.jms.MessageConsumer se cuelga al recibir cuando el consumidor cerró

Tengo un hilo en el que se está llamando a un receive(). Como parte del cierre del hilo, estoy llamando a close(), pero el consumidor todavía bloquea en receive() y, por lo tanto, el hilo no se apagará. La esencia de mi código es:

public String receiveMessage() { 
... 
... 
    System.out.println("About to receive") 
    TextMessage message = (TextMessage) consumer.receive(); 
    System.out.println("No longer receiving") 
... 
... 
} 

public void stop() { 
    try { 
     if (consumer != null) { 
      consumer.close(); 
     } 
    } catch (JMSException ex) { 
     throw new IllegalStateException(ex); 
    } 
} 

En el depurador que pueda ver de cerca() se llama, pero el recibir todavía bloques. Si utilizo el método receive() con un tiempo de espera, se bloqueará hasta que expire el tiempo de espera.

Todo me parece bien, con suerte alguien me puede decir lo que estoy haciendo mal.

+0

JMS es notoriamente específico para la implementación subyacente. Ayudaría si dijeras cuál estabas usando. – skaffman

+0

Gracias por responder. Es IBM MQ 7.0.0.2 – DaveRlz

+0

[receiveNoWait] (http://docs.oracle.com/javaee/1.4/api/javax/jms/MessageConsumer.html#receiveNoWait()) –

Respuesta

5

He resuelto el problema, no estaba haciendo una conexión.start() en ninguna parte. Una vez que lo puse, el MessageConsumer.receive() dejó de bloquear cuando lo cerré y todo funcionó como esperaba.

Gracias por sus sugerencias.

2
  1. Trate receive(long timeout), y no se olvide de comprobar que mesage devuelto no es null.
  2. Además de consumer.close(), también puede interrumpir el hilo de sondeo - si close() se implementa mal y no notifica al receptor bloqueado, esto lo despertará.
+0

Gracias por esto. Probé la versión de tiempo de espera de receive() y tengo el mismo problema: solo bloquea durante el resto del tiempo de espera, por lo que mi aplicación no se cerrará hasta que se complete el tiempo de espera, que no es exactamente lo que quiero. – DaveRlz

+0

Sí, otra cosa: si eso es parte de cerrar toda la aplicación, cierre el conjunto completo de objetos ('MessageConsumer',' Session', 'Connection'). –

4

Una reflexión más.

En JMS, Connection tiene varios subprocesos. Sesión y debajo (Consumidor, Productor, Mensaje, etc.) are not thread-safe. Si está accediendo a cualquiera de esas cosas que no son seguras para subprocesos desde múltiples subprocesos, usted es responsable de evitar el acceso de subprocesos múltiples.

El código que se muestra a continuación parece que está llamando a métodos de Consumer desde un par de hilos. Una violación de esa regla.

Puede ser más seguro cerrar el objeto Connection. Sin conflictos de subprocesos y ninguna implementación sensata haría lo correcto para limpiar los recursos asociados con la conexión.

+0

+1 - gracias por la sugerencia. – DaveRlz

2

Pero aún así, llamar a consumer.close() en otro subproceso no es lo correcto. Tendrá que hacer una conexión. Cierre cuál se encargará de cerrar todas las sesiones, consumidores, productores, etc. bajo esa conexión.

Cuestiones relacionadas