我发现了一些有趣的行为......我无法判断这是一个错误或无能,但目前倾向于无能。
即使有等待的消息,此代码也不会进入循环:
Message msg;
while ((msg = consumer.receiveNoWait()) != null) {
System.out.println(msg);
}
此代码进入循环,注意空赋值:
Message msg = null;
while ((msg = consumer.receiveNoWait()) != null) {
System.out.println(msg);
}
此代码在Windows 32bit上的Glassfish 3.1.1b10 HotSpot 1.6_26上运行。我想不出为什么第一个块不起作用的解释!
编辑/更新2011年7月13日:
首先,我开始停止Glassfish域并在每个请求的部署之间删除它,这仍然会发生:)
其次,我无法在Destination或Consumer上同步,因为这是Java EE代码。但是,我可以保证有可用的消息。其中大约有500个没有消费者。事实上,创建QueueBrowser会告诉我有可用的消息!
第三,这个程序打印“WORKS!”每次!!!哎呀!!!
public static void main(String[] args) {
Object obj;
if ((obj = getNotNull()) != null) {
System.out.println("worked!");
} else {
System.out.println("failed!");
}
}
static Object getNotNull() {
return new Object();
}
最后,我说的是我自己的无能。 ;)
答案 0 :(得分:3)
瑞恩说,看起来像是一场竞争。两个代码的字节码是相同的,除了额外的“astore”:
public static void code1() throws javax.jms.JMSException;
Code:
0: getstatic #2; //Field consumer:Ljavax/jms/MessageConsumer;
3: invokeinterface #3, 1; //InterfaceMethod javax/jms/MessageConsumer.receiveNoWait:()Ljavax/jms/Message;
8: dup
9: astore_0
10: ifnull 23
13: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
16: aload_0
17: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
20: goto 0
23: return
public static void code2() throws javax.jms.JMSException;
Code:
0: aconst_null
1: astore_0
2: getstatic #2; //Field consumer:Ljavax/jms/MessageConsumer;
5: invokeinterface #3, 1; //InterfaceMethod javax/jms/MessageConsumer.receiveNoWait:()Ljavax/jms/Message;
10: dup
11: astore_0
12: ifnull 25
15: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
18: aload_0
19: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
22: goto 2
25: return
}
如果您想测试此理论,请尝试以下代码:
Message msg;
String dummy = null;
while ((msg = consumer.receiveNoWait()) != null) {
System.out.println(msg);
}
这是一个noop,但字节码几乎与第二个代码相同(将“astore_0”更改为“astore_1”)。
顺便说一下,我用“receiveNoWait”得到了可怕的结果。我更喜欢“receive(smallTimeout)”,以避免缓冲区欠载等。答案 1 :(得分:1)
这对我来说听起来像是一场竞赛。没有实例化的对象声明将始终导致空值。您可能认为在第一种情况下有消息等着您,但我打赌没有消息。在条件循环之前,打印出对象的数量并验证结果行为。如果您处于多线程情况,请在必要时在消息队列上进行同步以促进此操作。我认为它的工作原理与预期一致。
答案 2 :(得分:0)
我的钱是在你没有运行你认为你的代码。你提到“在Glassfish 3.1.1b10上运行”,所以可能没有太多的单元测试方法,因此能够确定错误的位置变得更加困难。
有几种可能性可能会在一些奇怪的边缘情况下产生影响。
null
赋值对堆栈的引用进行了破坏,它允许对象进行垃圾回收,引用与弱/软/幻像/终结器引用一起使用的对象,或者可能仅更改内存分配时间和干扰竞争条件。答案 3 :(得分:0)
您是否有可能提供哪些消费者对象以及receiveNoWait()可能是什么?