javax.jms.MessageConsumer зависает при получении, когда потребитель закрыт - PullRequest
7 голосов
/ 04 ноября 2011

Согласно javadoc, если я вызову 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 () с таймаутом, он будет блокироваться до истечения времени ожидания.

Мне все кажется правильным, надеюсь, кто-нибудь скажет мне, что я делаю неправильно.

Ответы [ 4 ]

5 голосов
/ 05 ноября 2011

Я разобрался с проблемой, я нигде не делал connection.start (). Как только я вставил это, MessageConsumer.receive () прекратил блокировать, когда я закрыл это, и все работало, как я ожидал

Спасибо за ваши предложения.

5 голосов
/ 07 ноября 2011

Еще одна мысль.

В JMS соединение является многопоточным.Сеансы и ниже (Потребитель, Производитель, Сообщение и т. Д.) не являются потокобезопасными .Если вы обращаетесь к какой-либо из этих не поточно-безопасных вещей из нескольких потоков, вы несете ответственность за то, чтобы избежать многопоточного доступа.

Код, который вы показываете ниже, выглядит так, как будто вы вызываете методы из Consumer изпару ниток.Нарушение этого правила.

Возможно, безопаснее просто закрыть объект Connection.Никакие конфликты потоков и любая разумная реализация не сделают правильную вещь для очистки ресурсов, связанных с подключением.

3 голосов
/ 08 ноября 2011

Но, тем не менее, вызывать customer.close () в другом потоке - это неправильно.Вам нужно будет установить соединение. Закрыть, чтобы позаботиться о закрытии всех сессий, потребителей, производителей и т. Д. Под этим соединением.

2 голосов
/ 04 ноября 2011
  1. Попробуйте receive(long timeout), и не забудьте проверить, что возвращаемое сообщение не null.
  2. В дополнение к consumer.close() вы также можете прервать поток опроса - если close() реализован плохо и не уведомляет заблокированный получатель, это разбудит его.
...