In my application, I have one text field and a button. After focus lost from text field first swing worker (lets assume it as sw1) is called. Which opens a pop-up to populate value to put in text field. Second swing worker (lets assume it as sw2) is called after user clicks a button. Now the issue is that if I write something in text field and then click on button, sw1 is started first to calculate the value to put in text field and at the same time sw2 is also started. And sw2 finishes first and then sw1 populates result. What I want is sw2 should wait for sw1 to finish. Once sw1 finishes its task, it will notify sw2. I referred so many references over the internet and stackoverflow. This is the one which almost matches to my requirement. I tried to create a static final object inside class which starts sw1:
public final static Object lockObject = new Object();
Then inside done() method of sw1, I have written code like:
synchronized(lockObject) {
sw1.notifyAll();
}
Inside doInBackground() method, of the second class, on first line, I have written code like:
synchronized(FirstClass.lockObject) {
try {
sw2.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
But I am getting java.lang.IllegalMonitorStateException, at java.lang.Object.notifyAll(Native Method). Can anybody tell me what is the issue and how to make it work the way I want.
Update: As per Ernest's solution I modified my code and it looks like now:
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();
}
......
}
}
But still I am getting java.lang.IllegalMonitorStateException on lockObject.notifyAll() line. Can you please tell if I am doing it correctly?
Thanks.
Your code should look something like this.
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();
}
......
}
}
But. Synchronizing on a global static object will get you in trouble if you have more than one instance of FirstClass.java and SecondClass.java. You should really find a way to pass the object instances around.
If I understood correctly your use case, can't you simply disable the button for sw2 when the user starts editing the field, and re-enable it when the first worker finishes? It would be much more clear for the user as well.