我目前正在使用Swing GUI在Java(在Eclipse中)构建Game of Life模拟器,作为大学项目的一部分。除了一个小缺陷之外,这是奇妙的进展 -
它适用于我的上网本,但不适用于我尝试过的任何其他PC。这是在Ubuntu下。
一些结构轮廓 - 我有一个模型,一个视图和一个控制器。我还没有正确定义模型,但我已经完成了View(GUI部分)并启动了Controller。 Controller由Main方法运行,然后Controller在单独的线程中创建View类并进入while循环。
View实现了一个“订单”队列,它从用户输入,鼠标点击以及不是用户输入中获得。 Controller在while循环的迭代中从队列中选取这些命令,并根据需要执行它们。
然而,虽然代码在我的上网本(最新版本,Java 1.6.0_20)上工作正常,但它不能在我的PC上运行(最新版本,Java 1.6.0_20)或大学PC(karmic,以前的一些) Java版本)。一旦遇到'getNextCommand'方法,它就会停止。 没有错误,只是拒绝打印/遵守
源文件位于此处 - http://www.mediafire.com/?dfwtdkj1tdxd5xl 感兴趣的文件是Controller和View。
在View中,我有这个功能:
public Command getNextCommand() {
System.out.println(commands.getFirst().id);
return commands.pop();
}
非常明显,当Controller调用getNextCommand()时,它会打印出什么命令。
这是Controller中的while循环:
while(!stop) {
if (gui.hasCommand()){
order = gui.getNextCommand();
//System.out.println("Something");
//if(order.id.equals("stop")) { stop = true; }
}
}
这很好用。它会按照您的预期在getNextCommand中打印。
但是取消注释两个语句中的任何一个,它突然停止工作。不再为你打印了!
为什么会这样?为什么这会在我的上网本上运行,而不是我的PC呢? :C
此外,如果我运行Eclipse生成的.class文件,它会打印(假设这两行被注释掉)。如果我只是使用javac自己编译它们,则不会打印任何内容。
任何见解都将不胜感激!
谢谢,
路。
如果我在调用getNextCommand时返回一个Integer,而不是返回一个Command(一个带有id(String),x,y(int)和value(int)的简单容器类),则会出现同样的问题。或其他任何事情。
答案 0 :(得分:3)
嗯,这是一个多线程问题的经典案例,因为你从不同的线程调用视图和控制器。假设您的命令容器未同步。
令人高兴的是,命令的更新是由一个线程完成的,但是其他线程没有注意到它,因为更新不在synchronized块内。可以把它想象成两个线程处理不同的CPU缓存 - 当一个线程写入时,另一个线程没有看到它,除非它导致缓存被刷新到主存储器中 - 这只有在调用synchronized时才会发生。
更多信息:http://gee.cs.oswego.edu/dl/cpj/jmm.html
快速解决方案:使用java.util.vector而不是LinkedList
答案 1 :(得分:2)
我们需要更多信息。什么类型commands
?
无论哪种方式,比繁忙等待(在while循环中旋转)更好的解决方案是使用某种等待/通知机制。您问题的明显候选人似乎是BlockingQueue
(例如ArrayBlockingQueue
或LinkedBlockingQueue
)。这种类型的检索方法阻止直到有数据(命令)可用,而不是要求你在有可用命令之前不断轮询。
E.g。
BlockingQueue<Command> commands = new LinkedBlockingQueue<Command>();
//...
//wait for the next element and then get it
while(!stop) {
Command nextCommand = commands.take();
//do something with nextCommand
}
答案 2 :(得分:0)
更有可能是您没有捕获或未正确处理的错误。仔细检查您是否没有抛出异常。
此外,您尝试删除您认为不相关的程序部分,并确保它一直失败。这将帮助您确定真正的根本原因。