Reputation: 3
I would like to say that I tried to find some answers on this site but I couldn't manage, also this is my first question so I am sorry if i wrote it off format etc...
I am trying to learn java and now trying to understand thread section. So far I understood some basics and I wanted to try this: a lieutenant class shares the monitor-lock with a soldier class but I am failing at somewhere.
Edit: I want to Lieutenant waits until the Soldier says his first line, then he gives an order. But when soldier tries to release lock I get an monitor error because of notify method. "Exception in thread "Thread-1" java.lang.IllegalMonitorStateException."
P.S: I know there are easier ways but I am trying to utilize wait¬ify.
public class Lieutenant {
private boolean waitForCommand = true;
public void setWaitForCommand(boolean waitForCommand) {
this.waitForCommand = waitForCommand;
}
public synchronized void giveOrder() {
while (waitForCommand) {
try {
wait();
} catch (InterruptedException e) {
e.getStackTrace();
}
System.out.println("I said run soldier! RUN!");
}}}
public class Soldier {
private final Lieutenant lieutenant;
public Soldier(Lieutenant lieutenant) {
this.lieutenant = lieutenant;
}
public void getOrder() {
synchronized (this.lieutenant) {
System.out.println("Sir! Yes, sir!");
lieutenant.setWaitForCommand(false);
notifyAll();
}}}
class Main {
public static void main(String[] args) {
Lieutenant lieutenant = new Lieutenant();
Soldier soldier = new Soldier(lieutenant);
new Thread(new Runnable() {
@Override
public void run() {
lieutenant.giveOrder();
}}).start();
new Thread(new Runnable() {
@Override
public void run() {
soldier.getOrder();
}}).start();
}}
Upvotes: 0
Views: 66
Reputation: 886
The immediate problem here is with this method:
synchronized (this.lieutenant) {
System.out.println("Sir! Yes, sir!");
lieutenant.setWaitForCommand(false);
notifyAll();
}}
The synchronized block is holding a lock on this.lieutenant but you are attempting to call notifyAll() on this, which you aren't holding the lock on.
If make this change
synchronized (this.lieutenant) {
System.out.println("Sir! Yes, sir!");
lieutenant.setWaitForCommand(false);
this.lieutenant.notifyAll();
}}
It should work better. But as mentioned in the comments you can't guarantee that giveOrder will be called before getOrder.
Upvotes: 3