我发现一个Java代码作业的神秘问题。 一个朋友编程这个开头的应用程序:
public void run() { vm.setVisible(true); while(!end); System.out.println("Finish"); vm.setVisible(false); }
当所有执行和用户退出应用程序时,布尔“结束”都是假的:
private class CloseSys implements ActionListener { public CloseSys() {super();} public void actionPerformed(ActionEvent e) { System.out.println("CLOSE SYS"); System.out.println("end: "+end); end = true; System.out.println("end: "+end); } }
println在完成和应用程序中显示像'end'的值在我的朋友的计算机(MacOS)中真实和逻辑地转换。
问题是,在我的电脑(Ubuntu的Linux)的println也显示像价值的变化,但一段时间没有结束(“完成”println永远不会到达)。 有趣的是,如果我们把印刷品放在一边…然后工作!
end
必须是volatile
因为它在两个线程之间共享!
其他几个人提到它应该是不稳定的。 有一点似乎没有人提到,就是你“忙着等待”,这是错的,错的,错的错。 如果你想等待另一个线程发生什么事情,你应该使用同步锁或信号量 。
尽量让end
变量易变 – 你已经被多线程问题困扰了(并且你有一个多核CPU)。
这里有一些信息: http : //www.javamex.com/tutorials/synchronization_volatile_when.shtml
它看起来像一个线程问题。
尝试将end
声明为volatile
,或者更好地使用CountDownLatch
因为这可以避免占用CPU:
private CountDownLatch latch; public void run() { try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { vm.setVisible(true); } }); try { latch.await(); System.out.println("Finish"); } finally { SwingUtilities.invokeAndWait(new Runnable() { public void run() { vm.setVisible(false); } }); } } catch (InterruptedException ex) { System.out.println("Interrupt"); Thread.currentThread().interrupt(); } catch (InvocationTargetException ex) { throw new RuntimeException(ex); } } private class CloseSys implements Actionlistner { public void actionPerformed(ActionEvent e) { System.out.println("CLOSE SYS"); latch.countDown(); } }
请注意使用invokeAndWait
来更改来自非EDT线程的窗口可见性。