2011-11-04 8 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

私は問題をソートしましたが、どこにでも接続を開始していませんでした。これを入れたら、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複数のスレッドからスレッドセーフではないものにアクセスしている場合は、マルチスレッドアクセスを回避する必要があります。

以下に示すコードは、2つのスレッドからConsumerのメソッドを呼び出すようです。そのルール違反。

Connectionオブジェクトを閉じるほうが安全かもしれません。スレッドとの競合や適切な実装は、コネクションに関連するリソースをクリーンアップするのに適切なことではありません。

+0

+1 - チップのおかげで。 – DaveRlz

2

しかし、別のスレッドでconsumer.close()を呼び出すことは正しいことではありません。あなたは、その接続の下ですべてのセッション、コンシューマー、プロデューサーなどを閉鎖する世話をするconnection.Closeを行う必要があります。

関連する問題