不可能的Java内存一致性错误

不可能的Java内存一致性错误,java,multithreading,swing,memory,Java,Multithreading,Swing,Memory,首先,我不是一个以英语为母语的人,所以我为任何最终的“奇怪”的写作道歉 我正在Eclipse上开发一个Swing Java应用程序,用于更新Jpanel。这个面板包含几个子面板,我一直在切换面板的“模式”,鼠标听写器会发生变化,所以它们对用户鼠标输入的响应方式略有不同 不管应用程序做什么,它都会发生一个错误,我似乎没有任何逻辑上的解释。在我的代码中的某个时刻,我尝试将面板更新为我所称的neutralMode。这在以下方法中发生: //Guarded block (see http://docs.

首先,我不是一个以英语为母语的人,所以我为任何最终的“奇怪”的写作道歉

我正在Eclipse上开发一个Swing Java应用程序,用于更新Jpanel。这个面板包含几个子面板,我一直在切换面板的“模式”,鼠标听写器会发生变化,所以它们对用户鼠标输入的响应方式略有不同

不管应用程序做什么,它都会发生一个错误,我似乎没有任何逻辑上的解释。在我的代码中的某个时刻,我尝试将面板更新为我所称的neutralMode。这在以下方法中发生:

//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!方法范围是唯一定义集合可见大小的东西!有一件事是可以肯定的,那就是你所称的那些方法不会有任何区别,所以你可以完全肯定地排除这种可能性。忘记这一点,继续思考其他选择。再次关注“面板”的变化。您是否可以在此处共享完整文件,或者至少共享正在以任何方式更改收集面板的方法?干杯