2011-11-04 11 views
6

In base a javadoc, se si chiama receive() su un javax.jms.MessageConsumer, si blocca indefinitamente fino a quando non viene prodotto un messaggio o fino alla chiusura del consumer del messaggio.javax.jms.MessageConsumer si blocca quando viene chiuso il consumer

Ho una discussione in cui viene chiamato un receive(). Come parte dell'arresto del thread, sto chiamando close(), ma il consumer continua a bloccare in receive() e quindi il thread non si spegnerà. Il nocciolo del mio codice è:

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); 
    } 
} 

Nel debugger posso vedere close() essere chiamato, ma la ricezione ancora blocchi. Se utilizzo il metodo receive() con un timeout, verrà bloccato fino alla scadenza del timeout.

Tutto sembra giusto per me, si spera che qualcuno possa dirmi cosa sto facendo male.

+0

JMS è notoriamente specifico dell'implementazione sottostante. Sarebbe utile se tu dicessi quale stavi usando. – skaffman

+0

Grazie per la risposta. È IBM MQ 7.0.0.2 – DaveRlz

+0

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

risposta

5

Ho risolto il problema, non stavo facendo un connection.start() ovunque. Una volta inserito, MessageConsumer.receive() ha smesso di bloccare quando l'ho chiuso e tutto ha funzionato come mi aspettavo.

Grazie per i vostri suggerimenti.

2
  1. Prova receive(long timeout), e non dimenticare di controllare che mesage restituito non è null.
  2. Oltre allo consumer.close() è possibile interrompere anche il thread di polling: se lo close() è implementato in modo insufficiente e non notifica il ricevitore bloccato, questo lo riattiverà.
+0

Grazie per questo. Ho provato la versione di timeout di receive() e ho lo stesso problema - blocca solo per il resto del timeout e quindi la mia app non si chiuderà fino al completamento del timeout, che non è proprio quello che voglio. – DaveRlz

+0

Sì, un'altra cosa: se questo è parte dell'arresto dell'intera app, chiudi l'intero set di oggetti ('MessageConsumer',' Session', 'Connection'). –

4

Un ulteriore pensiero.

In JMS, la connessione è multi-thread. Sessione e di seguito (consumatore, produttore, messaggio, ecc.) are not thread-safe. Se stai accedendo a una di queste cose non thread-thread da più thread, sei responsabile di evitare l'accesso multi-thread.

Il codice che viene mostrato di seguito sembra che tu stia chiamando metodi su Consumer da un paio di thread. Una violazione di quella regola.

Potrebbe essere più sicuro chiudere semplicemente l'oggetto Connection. Nessun conflitto di threading e nessuna implementazione ragionevole farebbero la cosa giusta per ripulire le risorse associate con la Connection.

+0

+1 - grazie per il suggerimento. – DaveRlz

2

Tuttavia, chiamare consumer.close() su un altro thread non è la cosa giusta da fare. Dovrai fare una connessione.Chiudi che si occuperà di chiudere tutte le sessioni, i consumatori, i produttori ecc. Sotto questa connessione.

Problemi correlati