[英]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.