Can anyone explain this program on inter-thread communication?
// A correct implementation of a producer and consumer.
class Q {
int n;
boolean valueSet = false;
synchronized int get() {
while(!valueSet)
try {
wait();
} catch(InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n) {
while(valueSet)
try {
wait();
} catch(InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}
class Producer implements Runnable {
Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
public void run() {
int i = 0;
while(true) {
q.put(i++);
}
}
}
class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while(true) {
q.get();
}
}
}
class PCFixed {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-C to stop.");
}
}
Output
Put: 1 Got: 1 Put: 2 Got: 2 Put: 3 Got: 3 Put: 4 Got: 4 ......
It is very confusing as far as I am concerned, especially the put and get methods where notify() and wait() are used. Please also explain why a boolean value is used.
So there are 2 threads. Qne is setting values on this Q data structure and the other is reading them. Q uses a boolean flag to tell whether a new value is present, the flag gets cleared once an existing value is read.
Q.get uses wait to block until a new value is available to read. Once it's read the new value it sets the flag back to false.
Q.put waits until the other queue has read the new value before setting it to a new value, then lets the other thread know by setting the boolean flag and calling notify.
Remember that wait gives up the lock so the other thread can acquire it.
The boolean flag is needed because a thread may stop waiting without having been notified. Just because a thread woke up doesn't mean it got a notification. Also, even if the thread gets notified, since the thread gave up the lock when it started to wait, the current state of things is unknown (in general there are multithreaded programs where another thread might sneak in and snag something between the time a thread is notified and the time it can regain the lock) so the thread has to re-test the condition again once it has the lock.
Constructs like wait and notify are building blocks for large concurrent programs, so some things may not make as much sense in a small example with only two threads.