2011-11-04 10 views
6

Zgodnie z javadoc, jeśli wywołasz metodę receive() na javax.jms.MessageConsumer, będzie ona blokować się w nieskończoność, dopóki nie zostanie wygenerowany komunikat lub dopóki użytkownik wiadomości nie zostanie zamknięty.javax.jms.MessageConsumer zawiesza się na odbiór po zamknięciu konsumenta

Mam wątek, w którym wywoływana jest funkcja receive(). W ramach zamykania wątku wywołuję metodę close(), ale konsola nadal blokuje funkcję receive(), dlatego wątek nie zostanie zamknięty. Istotą mojego kodu jest:

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

W debugerze widzę wywołanie metody close(), ale odbieranie bloków nadal. Jeśli użyję metody receive() z limitem czasu, będzie ona blokowana do momentu wygaśnięcia limitu czasu.

Wszystko wygląda dobrze dla mnie, mam nadzieję, że ktoś może mi powiedzieć, co robię źle.

+0

JMS jest znany z podstawowej implementacji. Pomoże ci, jeśli powiesz, z którego używasz. – skaffman

+0

Dzięki za odpowiedź. To IBM MQ 7.0.0.2 – DaveRlz

+0

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

Odpowiedz

5

Posortowałem problem, nie robiłem połączenia.start() w dowolnym miejscu. Kiedy już to wstawiłem, funkcja MessageConsumer.receive() przestała blokować, gdy ją zamknąłem i wszystko działało zgodnie z oczekiwaniami.

Dzięki za sugestie.

2
  1. Spróbuj receive(long timeout), i nie zapomnij, aby sprawdzić, czy nie jest zwracana mesage null.
  2. Oprócz consumer.close() możesz również przerwać wątek odpytywania - jeśli close() jest źle zaimplementowany i nie powiadamia zablokowanego odbiornika, spowoduje to jego wybudzenie.
+0

Dzięki za to. Próbowałem już timeoutowej wersji metody receive() i mam ten sam problem - blokuje się tylko na resztę limitu czasu, więc moja aplikacja nie zostanie zamknięta do czasu zakończenia limitu czasu, co nie jest tym, czego chcę. – DaveRlz

+0

Tak, co innego - jeśli jest to częścią wyłączania całej aplikacji, zamknij pełny zestaw obiektów ('MessageConsumer',' Session', 'Connection'). –

4

Jeszcze jedna myśl.

W JMS połączenie jest wielowątkowe. Sesja i poniżej (konsument, producent, wiadomość itp.) are not thread-safe. Jeśli uzyskujesz dostęp do tego nieistotnego wątku z wielu wątków, odpowiadasz za unikanie dostępu wielowątkowego.

Poniższy kod wygląda tak, jak wywołujesz metody na Konsumencie z kilku wątków. Naruszenie tej zasady.

Bezpieczniejsze może być po prostu zamknięcie obiektu Connection. Żadne konflikty wątków i żadna rozsądna implementacja nie powinny czyścić odpowiednich zasobów w połączeniu.

+0

+1 - dziękuję za cynk. – DaveRlz

2

Ale nadal wywoływanie consumer.close() w innym wątku nie jest właściwym rozwiązaniem. Będziesz musiał wykonać połączenie. Zamknij, które zajmie się zamknięciem wszystkich sesji, konsumentów, producentów itp. W ramach tego połączenia.

Powiązane problemy