javax.jms.MessageConsumer hangs on receive when consumer closed
Solution 1
I've sorted the problem, I wasn't doing a connection.start() anywhere. Once I put this in, the MessageConsumer.receive() stopped blocking when I closed it and everything worked as I had expected.
Thanks for your suggestions.
Solution 2
One further thought.
In JMS, Connection is multi-threaded. Session and below (Consumer, Producer, Message, etc) are not thread-safe. If you're accessing any of that non-thread-safe stuff from multiple threads, you're responsible for avoiding multi-threaded access.
The code you show below looks like you're calling methods on Consumer from a couple of threads. A violation of that rule.
It might be safer to just close the Connection object. No threading conflicts and any sensible implementation would do the right thing to clean up resources associated w/ the Connection.
Solution 3
But still, calling consumer.close() on another thread is not the right thing to do. You will need to do a connection.Close which will take care of closing all sessions, consumers, producers etc under that connection.
Solution 4
- Try
receive(long timeout)
, and don't forget to to check that returned mesage is notnull
. - In addition to
consumer.close()
you may also interrupt polling thread - ifclose()
is implemented poorly and doesn't notify blocked receiver, this will wake it up.
Comments
-
Dave Richardson about 2 years
According to the javadoc, if I call receive() on a javax.jms.MessageConsumer it will block indefinitely until a message is produced or until the message consumer is closed.
I have a thread in which a receive() is being called. As part of the thread shutdown I am calling close(), but the consumer still blocks in receive() and so the thread will not shutdown. The gist of my code is:
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); } }
In the debugger I can see close() being called, but the receive still blocks. If I use the receive() method with a timeout it will block until the timeout expires.
Everything looks right to me, hopefully someone can tell me what I am doing wrong.
-
Dave Richardson over 12 yearsThanks for this. I've tried the timeout version of receive() and I have the same problem - it just blocks for the remainder of the timeout and so my app won't close down until the timeout is complete, which is not quite what I want.
-
Andrey Nudko over 12 yearsYeah, another thing - if that's part of shutting down the whole app, close the full set of objects (
MessageConsumer
,Session
,Connection
). -
hB0 over 2 yearsBut @Shashi above mentioned: "You will need to do a connection.Close which will take care of closing all sessions, consumers, producers etc under that connection."