2011-11-04 56 views
6

根據javadoc,如果我調用javax.jms.MessageConsumer上的receive(),它將無限期地阻塞,直到生成消息或消息使用者關閉。javax.jms.MessageConsumer在消費者關閉時掛起接收

我有一個線程在調用receive()。作爲線程關閉的一部分,我調用close(),但消費者仍然在receive()中阻塞,所以線程不會關閉。我的代碼的要點是:

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

在調試器中,我可以看到close()被調用,但接收仍然阻塞。如果我使用帶有超時的receive()方法,它將阻塞,直到超時過期。

一切看起來都適合我,希望有人能告訴我我做錯了什麼。

+0

JMS是臭名昭着的特定於底層實現。如果你說出你正在使用哪一個,這將有所幫助。 – skaffman

+0

感謝您的回覆。它是IBM MQ 7.0.0.2 – DaveRlz

+0

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

回答

5

我已經排序的問題,我沒有做一個connection.start()的任何地方。一旦我把它放入,MessageConsumer.receive()在我關閉它時停止了阻塞,並且一切都按我的預期工作。

感謝您的建議。

2
  1. 嘗試receive(long timeout),不要忘記檢查返回的消息不是null
  2. 除了consumer.close()你也可能會中斷輪詢線程 - 如果close()執行得不好並且不通知被阻塞的接收方,這會喚醒它。
+0

感謝此。我試過了receive()的超時版本,而且我遇到了同樣的問題 - 它只是阻塞了超時的剩餘時間,所以我的應用程序不會關閉,直到超時完成,這並不是我想要的。 – DaveRlz

+0

是的,另一件事 - 如果這是關閉整個應用程序的一部分,關閉全套對象('MessageConsumer','Session','Connection')。 –

4

還有一個想法。

在JMS中,Connection是多線程的。會議及以下(消費者,製片人,留言等)are not thread-safe。如果你從多個線程訪問任何非線程安全的東西,你有責任避免多線程訪問。

您在下面顯示的代碼看起來像是從幾個線程調用Consumer上的方法。違反該規定。

只關閉Connection對象可能會更安全。沒有線程衝突和任何明智的實現會清理與Connection相關的資源。

+0

+1 - 感謝您的提示。 – DaveRlz

2

但是,在另一個線程上調用consumer.close()並不是正確的做法。你將需要做一個連接。關閉這將關閉關閉所有會議,消費者,生產者等在該連接下。

相關問題