不可能的Java内存一致性错误
首先,我不是一个以英语为母语的人,所以我为任何最终的“奇怪”的写作道歉 我正在Eclipse上开发一个Swing Java应用程序,用于更新Jpanel。这个面板包含几个子面板,我一直在切换面板的“模式”,鼠标听写器会发生变化,所以它们对用户鼠标输入的响应方式略有不同 不管应用程序做什么,它都会发生一个错误,我似乎没有任何逻辑上的解释。在我的代码中的某个时刻,我尝试将面板更新为我所称的neutralMode。这在以下方法中发生:不可能的Java内存一致性错误,java,multithreading,swing,memory,Java,Multithreading,Swing,Memory,首先,我不是一个以英语为母语的人,所以我为任何最终的“奇怪”的写作道歉 我正在Eclipse上开发一个Swing Java应用程序,用于更新Jpanel。这个面板包含几个子面板,我一直在切换面板的“模式”,鼠标听写器会发生变化,所以它们对用户鼠标输入的响应方式略有不同 不管应用程序做什么,它都会发生一个错误,我似乎没有任何逻辑上的解释。在我的代码中的某个时刻,我尝试将面板更新为我所称的neutralMode。这在以下方法中发生: //Guarded block (see http://docs.
//Guarded block (see http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html)
private synchronized boolean waitsForUserSatisfactionAnswer()
{
while(!userIndicatedSatisfaction)
{
try {
wait();
} catch (InterruptedException e) {}
}
userIndicatedSatisfaction = false; //reset for future new query
getObjectSetVisualizationPanel().neutralMode();
//getObjectSetVisualizationPanel().queryPatternMode();
return userSatisfied;
}
此更新不起作用(对neutralMode()的调用不符合预期)。但是,对queryPatternMode()的调用(在下面的行中注释)工作得非常好。所以我决定复制queryPatternMode()的主体,并将其粘贴到neutralMode()的主体上!但它仍然不起作用
方法代码如下所示:
public void queryPatternMode()
{
System.out.println("Inside queryPatternMode!!!");
System.out.println("panels.size(): " + panels.size());
for (DigitalObjectPanel panel : panels)
{
System.out.println("Inside the loop!!!");
panel.resetBehavior();
panel.setQuerySelectionBehavior(gui);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
panel.validate();
}
});
}
}
public void neutralMode()
{
System.out.println("Inside neutralMode!!!");
System.out.println("panels.size(): " + panels.size());
for (DigitalObjectPanel panel : panels)
{
System.out.println("Inside the loop!!!");
panel.resetBehavior();
panel.setQuerySelectionBehavior(gui);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
panel.validate();
}
});
}
}
当我调用neutralMode()时,“panels”集合恰好为空(panels.size()等于零)。但是,当我调用queryPatternMode()时,集合恰好具有预期的大小(20个面板)。但是这两个方法都是相等的,并且都是从同一个地方调用的
可能是什么???有什么可能的解释吗???这看起来确实像是一个同步问题。您应该检查有多少线程正在访问集合“面板”
幸运的是,它始终适用于queryPatternMode(),而不适用于neutralMode()。在另一个晴朗的日子,情况可能会相反。您是否在
面板的什么范围内更新了所有Swing对象?也许你在用一种方法隐藏它,但不是用另一种方法?你的IDE怎么说?将面板
替换为this.panels
会改变什么吗?您有完整的功能示例可以尝试吗?您的代码似乎忽略了事件驱动编程的原则。通常,您不应该连续轮询变量,例如userindicatedsatisfion
,而是使用侦听器或观察者模式,从而收到更改通知。根据其他人的建议,考虑创建和发布A.是的,我在EDT上做所有的UI更新。panels是私有成员,两个方法都来自panels所属的同一类。IDE什么也没说,根本没有异常或错误,它只是在应用程序行为上。我只是试着改成this.panels,但不起作用……轮询是oracle java教程建议的一种称为保护块的习惯用法。毕竟,它似乎工作得很好,while条件检查是为了防止意外醒来。当我调用“mode”方法时,问题就出现了。具体的方法范围是定义面板的可见大小,这根本没有意义!谢谢你的回答。起初,我还认为这是一个同步问题,所以我尝试了几种修复方法:-声明面板列表易失性-同步两种方法-更改面板访问权限仅限于包装器同步方法-尝试将面板集合从arralist切换到vector-尝试通过集合获取面板。synchronizedList()这些都不起作用。此外,即使考虑到线程问题,这似乎也毫无意义,因为我从完全相同的点调用方法,并且两者都执行相同的代码。此外,还发生了一些奇怪的事情:我试图将neutralMode()委托给queryPatternMode(),所以我在neutralMode()上打印面板大小然后调用queryPatternMode()并再次打印面板大小。而且集合的大小仍然不同!先是0,然后是20!方法范围是唯一定义集合可见大小的东西!有一件事是可以肯定的,那就是你所称的那些方法不会有任何区别,所以你可以完全肯定地排除这种可能性。忘记这一点,继续思考其他选择。再次关注“面板”的变化。您是否可以在此处共享完整文件,或者至少共享正在以任何方式更改收集面板的方法?干杯