在我的应用程序中,我有一个文本字段和一个按钮。从文本字段丢失焦点后,第一个摇摆工作者(假设它为sw1)被调用。这会打开一个弹出窗口以填充值以放入文本字段。在用户单击按钮后调用第二个swing工作者(假设它为sw2)。 现在的问题是,如果我在文本字段中写入内容然后单击按钮,则首先启动sw1以计算要放入文本字段的值,同时也启动sw2。并且sw2首先完成,然后sw1填充结果。我想要的是sw2应该等待sw1完成。一旦sw1完成任务,它将通知sw2。 我通过互联网和stackoverflow引用了很多引用。 This是几乎符合我要求的那个。 我试图在类中创建一个静态的final对象,它启动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。你能否告诉我,我是否正确行事?
感谢。
答案 0 :(得分: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按钮,并在第一个工作完成后重新启用它吗?对用户来说也会更清楚。
答案 1 :(得分:2)
您无需重新发明这样一个简单的同步工具。例如,您可以使用CountDownLatch。 Sw1做倒计时和sw2 - 等待。
答案 2 :(得分:1)
您只能在您持有其监视器的对象上调用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()
。)对于{{{{{ 1}},但两个线程中的代码必须同意使用相同的对象。