繁体   English   中英

不明原因的Java恶作剧 - 可能与线程有关吗?

[英]Unexplained Java shenanigans - possibly to do with threading?

问题

我目前正在使用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而不是返回一个Command(一个带有id(String),x,y(int)和value(int)的简单容器类)而返回一个Integer,则会出现同样的问题。 或其他任何东西。

嗯,这是一个多线程问题的经典案例,因为你从不同的线程调用视图和控制器。 假设您的命令容器未同步。

令人高兴的是,命令的更新是由一个线程完成的,但是其他线程没有注意到它,因为更新不在同步块内。 可以把它想象成两个线程处理不同的CPU缓存 - 当一个线程写入时,另一个线程没有看到它,除非它导致缓存被刷新到主存储器中 - 这只有在调用synchronized时才会发生。

更多信息: http//gee.cs.oswego.edu/dl/cpj/jmm.html

快速解决方案:使用java.util.vector而不是LinkedList

我们需要更多信息。 commands是什么类型的?

无论哪种方式,比繁忙等待(在while循环中旋转)更好的解决方案是使用某种等待/通知机制。 您问题的明显候选者似乎是BlockingQueue (如ArrayBlockingQueueLinkedBlockingQueue )。 此类型的检索方法将阻塞, 直到有可用的数据(命令),而不是要求您在有可用命令之前不断轮询。

例如

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
}

参考

更可能的是,您没有捕获或未正确处理的错误。 仔细检查您是否没有抛出异常。

此外,您尝试删除您认为不相关的程序部分,并确保它一直失败。 这将帮助您确定真正的根本原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM