0

在我的应用程序中,我有一个文本字段和一个按钮。在文本字段失去焦点后,第一个摇摆工人(假设它是 sw1)被调用。这会打开一个弹出窗口来填充要放入文本字​​段的值。在用户单击按钮后调用第二个摇摆工人(假设它为 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。谁能告诉我问题是什么以及如何使它按我想要的方式工作。

更新:根据欧内斯特的解决方案,我修改了我的代码,现在看起来像:

    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 。你能告诉我这样做是否正确吗?

谢谢。

4

3 回答 3

2

您的代码应该看起来像这样。

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 的按钮,并在第一个工作人员完成时重新启用它吗?这对用户来说也会更清楚。

于 2012-07-13T15:40:04.413 回答
2

您无需重新发明这样一个简单的同步工具。例如,您可以使用CountDownLatch。Sw1 倒计时和 sw2 - 等待。

于 2012-07-13T15:40:28.243 回答
1

您只能在您持有其监视器的对象上调用wait()notify()。在您的每个代码片段中,您锁定了一个对象,但在另一个对象上调用这些方法。它只是不那样工作。恐怕我不能完全弄清楚你想要做什么,所以很难给你具体的更正,但基本上,这些块需要看起来像

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

假设有两个线程,T1 和 T2,并且有一些对象 O1。然后,如果线程 T1 上运行的代码想要等到线程 T2 中的代码说可以继续,它必须在 object 上同步O1,然后调用O1.wait(). 当在 T2 上运行的代码想要将该消息发送到 T1 时,它必须同步O1并调用O1.notify()(或O1.notifyAll())。您使用什么对象无关紧要O1,但两个线程中的代码必须同意使用同一个对象。

于 2012-07-13T13:52:11.727 回答