Groovy Closure执行奇怪

时间:2016-01-12 01:53:02

标签: groovy closures

我有一个基本上使用JMS消息的类,然后继续用这些消息调用一个闭包。消息监听器在一个单独的线程中运行。

import groovy.util.logging.Slf4j
import javax.jms.*

@Slf4j
class JMSProducer {

    Connection connection
    List<Queue> queues
    private Session session
    private List<MessageConsumer> messageConsumers

    @Override
    void init() {
        connection.start()
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)
        messageConsumers = queues.collect { session.createConsumer(it) }
    }

    @Override
    void produce(final Closure closure) {

        def listener = new MessageListener() {
            @Override
            void onMessage(Message message) {
                if (message instanceof ObjectMessage) {
                    try {
                        log.info("Calling");
                        closure.call(message.object);
                        log.info("Called");
                    } catch(e) {
                        log.error("Error")
                    } finally {
                        log.info("Finally");
                    }
                } else {
                    log.error("Unrecognized message")
                }
            }
        }
        messageConsumers.each {
            it.messageListener = listener
        }
    }
}

我对上述代码的问题是我看到&#34; Calling&#34;,&#34; Called&#34;和#34;最后&#34;对于我放入队列的所有消息,但是封闭本身只被称为其中的一小部分。

//Assume 5 messages have been put into queue, and 
// JMSProducer has been configured to read from queue*

new JMSProducer().produce { message ->
    log.info("Received Message");        
}

&#34;收到的消息&#34;仅记录两次(即使我看到&#34;呼叫&#34; /&#34;呼叫&#34; /&#34;最后&#34;每次五次)。

这几乎就像关闭被忽略或被忽略一样。

当我在IDE中运行时,我没有这个问题,只有在运行时  来自命令行的./gradlew clean test

最终它似乎是一种竞争条件,但我不知道如何在关闭执行之前和之后记录,而不会看到应该在闭包内部发生的记录。

作为更新,我添加了代码以在运行时注销闭包对象,并且我看到了以下输出(代码在调试中稍有变化,但问题仍然存在):

2016-01-12 14:56:04 INFO  JMSProducer - Calling: StreamUtil$2@1edef6f9
2016-01-12 14:56:04 INFO  JMSProducer - Calling:JMSProducerTest$_verifyJMSProducer_closure1@fa11e9d
2016-01-12 14:56:04 INFO  JMSProducer - Called
2016-01-12 14:56:04 INFO  JMSProducer - Finally
2016-01-12 14:56:04 INFO  JMSProducer - Called
2016-01-12 14:56:04 INFO  JMSProducer - Finally
2016-01-12 14:56:04 INFO  JMSProducer - Calling: StreamUtil$2@1edef6f9
2016-01-12 14:56:04 INFO  JMSProducer - Calling: JMSProducerTest$_verifyJMSProducer_closure1@fa11e9d
2016-01-12 14:56:04 INFO  JMSProducer - Called
2016-01-12 14:56:04 INFO  JMSProducer - Finally
2016-01-12 14:56:04 INFO  JMSProducer - Called
2016-01-12 14:56:04 INFO  JMSProducer - Finally
2016-01-12 14:56:04 INFO  JMSProducer - Calling: JMSProducerTest$_verifyJMSProducer_closure1@fa11e9d
2016-01-12 14:56:04 INFO  JMSProducer - Called
2016-01-12 14:56:04 INFO  JMSProducer - Finally

看起来回调并不是一致的。只有当我得到StreamUtil $ 2时,@ 1edef6f9才会执行回调。

1 个答案:

答案 0 :(得分:1)

好的,显然JMS中存在竞争条件,之前的测试以某种方式能够覆盖消息侦听器(但仅适用于部分迭代)。不完全确定是怎么发生的,但是与异步测试和JUnit有关。