繁体   English   中英

Java:swing worker线程同步

[英]Java: swing worker thread synchronization

在我的应用程序中,我有一个文本字段和一个按钮。 从文本字段失去焦点之后,将调用第一个挥杆工(假设它为sw1)。 这将打开一个弹出窗口,以填充要输入到文本字段中的值。 用户单击按钮后,将调用第二个Swing Worker(假设它为sw2)。 现在的问题是,如果我在文本字段中写一些东西然后单击按钮,则首先启动sw1以计算要放入文本字​​段的值,同时还启动sw2。 sw2首先完成,然后sw1填充结果。 我想要的是sw2应该等待sw1完成。 sw1完成任务后,将通知sw2。 我通过互联网和stackoverflow引用了很多参考。 几乎符合我的要求。 我试图在启动sw1的类中创建一个静态最终对象:

public final static Object lockObject = new Object();

然后在sw1的done()方法中,我编写了如下代码:

synchronized(lockObject) {
        sw1.notifyAll();
}

在第二类的doInBackground()方法内部,在第一行中,我编写了如下代码:

synchronized(FirstClass.lockObject) {
    try {
        sw2.wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

但是我在java.lang.Object.notifyAll(Native Method)处收到java.lang.IllegalMonitorStateException。 谁能告诉我问题是什么以及如何使其以我想要的方式工作。

更新:根据Ernest的解决方案,我修改了代码,看起来像现在这样:

    FirstClass.java

    public final static Object lockObject = new Object();

    public static boolean flag = false;

    someMethod() {
        synchronized(lockObject){
            sw1.doInbackground() {
            ......
            }

            sw1.done() {
            .....
            flag = true;
            lockObject.notifyAll();
            }

        }
    }


    SecondClass.java

    anotherMethod() {
        sw2.doInbackground() {
            try {
                while (!FirstClass.flag) {
                    FirstClass.lockObject.wait();
                }
                FirstClass.flag = false;
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            ......
        }

    }

但是我仍然在lockObject.notifyAll()行上得到java.lang.IllegalMonitorStateException。 你能告诉我我做得对吗?

谢谢。

您的代码应如下所示。

FirstClass.java

public final static Object lockObject = new Object();

public static boolean flag = false;

someMethod() {
    sw1.doInbackground() {
    ......
    }

    sw1.done() {
    .....
    }

    synchronized(lockObject){
        flag = true;
        lockObject.notifyAll();
    }
}


SecondClass.java

anotherMethod() {
    sw2.doInbackground() {
        try {
            synchronized(lockObject){
                while (!FirstClass.flag) {
                    FirstClass.lockObject.wait();
                }
                FirstClass.flag = false;
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        ......
    }

}

但。 如果您具有多个FirstClass.java和SecondClass.java实例,则在全局静态对象上进行同步将使您遇到麻烦。 您应该真正找到一种方法来传递对象实例。

如果我正确理解了您的用例,您是否不能简单地在用户开始编辑字段时就禁用sw2按钮,而在第一个工作人员完成操作后重新启用它呢? 对于用户来说也将更加清楚。

您无需重新发明这种简单的同步工具。 例如,您可以使用CountDownLatch Sw1不倒数,而sw2-等待。

您只能在您持有监视器的对象上调用wait()notify() 在每个代码段中,您都在锁定一个对象,但在另一个对象上调用这些方法。 就是那样行不通。 恐怕我无法完全弄清您要做什么,因此很难为您提供具体的更正,但是基本上,这些块需要看起来像

synchronized(sw2) {
    try {
        sw2.wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

假设有两个线程,T1和T2,并且有一些对象O1。 然后,如果在线程T1上运行的代码想要等待,直到线程T2中的代码说可以继续,则它必须在对象O1上进行同步,然后调用O1.wait() 当在T2上运行的代码想要将该消息发送到T1时,它必须在O1同步并调用O1.notify() (或O1.notifyAll() 。)对于O1使用哪个对象都没有关系,但是其中的代码两个线程必须同意使用同一对象。

暂无
暂无

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

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