Java JMS ActiveMQ - 关闭用于使用 MessageListener

问题描述

我在 JAVA 中有一个使用 ActiveMQ 的应用程序。按照为每个消费者使用特定“会话”的建议(以避免来自不同线程的会话并发问题),我在创建每个新消费者之前创建一个新会话。这些消费者使用 MessageListener 以异步方式收集他们的消息。

当消费者关闭时,我还想关闭用于(并显式创建)以创建此消费者的会话,但我无权访问用于创建我将要关闭的特定消费者的会话(此方法不存在于消费者的“MessageConsumer”对象中)。 我不想让所有这些会话保持打开状态,因为消费者正在动态连接和断开连接,并且最终打开(和未使用)的会话数量会非常高。

有没有办法访问用于创建使用 MessageListener 的特定“消费者”(MessageConsumer 对象)的“会话”?

当使用 MessageListerner 的使用者关闭时,还有其他方法可以关闭会话吗?

另一种可能性是自动清除没有任何关联资源(消费者、生产者等)的“会话”吗?

这是我的代码片段:

    Session session = connection.createSession(false,Session.AUTO_ACKNowLEDGE);
    MessageConsumer consumer = session.createConsumer(session.createQueue(queueName));
    consumer.setMessageListener(new CustomMessageListener(locWSInstance));

解决方法

您可以将会话和使用者传递给您的 CustomerMessageListener,它可以在 CustomMessageListener 的关闭生命周期内调用 close。否则,您需要某种 Manager/Tracker 类来跟上所有对象,以防止资源/内存泄漏。这与JDBC没有什么不同!有状态通信带来了性能和好处,但您必须将清理情况作为权衡。

  1. 使用 PooledConnectionFactory

  2. 一定要对生命周期逻辑进行单元测试。这是等待发生的资源泄漏/内存泄漏。

  3. 每个 对象周围执行适当的 try { } catch {} finally {} 逻辑,以确保对所有对象调用 close,并且您不会在 .close( ) 方法在调用所有 .close() 之前抛出异常并退出代码路径(见下文)

     public void deactivate() {
    
         if(consumer != null) {
            try {
                consumer.close();
            } catch (JMSException e) {
                // do some logging
            } finally {
                consumer = null;
            } 
         }
    
        if(session != null) {
            try {
                session.close();
            } catch (JMSException e) {
                // do some logging
            } finally {
                session = null;
            } 
         }
     }