首页 文章

即使队列在activemq中不为空,JMS实现中的receiveNoWait也返回null

提问于
浏览
1

我正在尝试在我的项目中实现JMS . 我使用活动mq作为提供程序,并使用持久队列 . 以下是从活动mq中检索元素的代码

conn = GlobalConfiguration.getJMSConnectionFactory().createConnection();
            conn.start();
            session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageConsumer consumer = session.createConsumer(queue);
            ObjectMessage obj = (ObjectMessage) consumer.receiveNoWait();

此代码有时返回数据,有时它返回null,即使我在活动的mq管理控制台中可以看到待处理消息的数量为非零 . 我阅读了很多文章,很少有人提到JMS api并没有强制要求你每次都获得元素,你必须相应地编写代码 . 因为在我的场景中,我依赖于队列,一旦队列返回null,我就杀了进程,所以我用以下方式修改了代码

我没有调用receiveNoWait,而是在通过队列浏览器检查队列中是否存在元素之后开始使用receive . 以下是修改后的代码

public static <T> T retrieveObjectFromQueue(Queue queue, Class<T> clazz) {
synchronized (queue) {
    if(!queueHasMoreElements(queue))
        return null;
    Connection conn = null;
    Session session = null;
    try {
        conn = GlobalConfiguration.getJMSConnectionFactory().createConnection();
        conn.start();
        session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageConsumer consumer = session.createConsumer(queue);
        ObjectMessage obj = (ObjectMessage) consumer.receive();
        return clazz.cast(obj.getObject());
    } catch(Exception e) {
        throw new RuntimeException(e);
    }finally {
        closeSessionAndConnection(session, conn);
    }
}


public static boolean queueHasMoreElements(Queue queue) {
Connection conn = null;
Session session = null;
try {
    conn = GlobalConfiguration.getJMSConnectionFactory().createConnection();
    conn.start();
    session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
    QueueBrowser browser = session.createBrowser(queue);
    Enumeration enumeration = browser.getEnumeration();
    return enumeration.hasMoreElements();
} catch(Exception e) {
    throw new RuntimeException(e);
}finally {
    closeSessionAndConnection(session, conn);
}

现在我的代码在处理了大约20-30个元素后卡住了,再次,我可以在管理控制台中看到待处理的元素 . 当我尝试使用调试模式时,我意识到,在检索了20-30个元素之后,我的代码卡在了consumer.receive(),这在情况队列为空时是预期的,但是当我检查我的管理控制台时,它显示了很多队列中的元素 .

我使用jdbc(mysql)作为activemq的持久存储 . 我正在使用的配置xml在activemq配置示例中给出(activemq / examples / conf / activemq-jdbc-performance.xml)

我使用tcp:// localhost:61616?jms.prefetchPolicy.queuePrefetch = 1作为activemq url .

请让我知道我做错了什么 . 我正在使用java8和apache activeMq 5.13.1

谢谢

1 回答

  • 1

    JMS规范也没有强制要求QueueBrowser返回队列中的所有消息,您可能只会根据很多因素获得启动时的内容快照 .

    您试图在JMS上强加语义,但它并不能保证 . 您可以尝试将预取设置为零,这将导致客户端轮询代理以获取消息,并等待代理告知有或没有消息 . 如果在您轮询时消息尚未到达队列,您可能仍然无法获得任何内容,这只是您需要处理的内容 .

    您还可以使用定时接收方法并强制执行您希望在返回和终止应用程序之前等待的超时 .

相关问题