While I do understand the Gist of inter thread communication and the usage of wait and notify on the monitor to ensure Put/Get operations are synchronized - I'm trying to understand why we need the Thread.sleep() in the code below for both producer and consumer when we have a working wait/notify mechanism? If I remove the thread.sleep() - the output goes to hell!
import java.io.*;
import java.util.*;
public class Test {
public static void main(String argv[]) throws Throwable {
Holder h = new Holder();
Thread p = new Thread(new Producer(h), "Producer");
Thread c = new Thread(new Consumer(h), "Consumer");
p.start();
c.start();
}
}
class Holder {
int a;
volatile boolean hasPut;
public synchronized void put(int i) {
while (hasPut) {
try {
System.out.println("The thread " + Thread.currentThread().getName() + " Going ta sleep...");
wait(1000);
} catch(Exception e) {
e.printStackTrace();
}
}
this.a = i;
hasPut = true;
notifyAll();
}
public synchronized int get() {
while (!hasPut) {
try {
System.out.println("The thread " + Thread.currentThread().getName() + " Going ta sleep...");
wait(1000);
} catch(Exception e) {
e.printStackTrace();
}
}
hasPut = false;
notifyAll();
return this.a;
}
}
class Producer implements Runnable {
Holder h;
public Producer(Holder h) {
this.h = h;
}
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("Putting : "+i);
h.put(i);
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
}
}
}
}
class Consumer implements Runnable {
Holder h;
public Consumer(Holder h) {
this.h = h;
}
public void run() {
for (int i = 0; i < 1000; i++) {
int k = h.get();
System.out.println("Getting : "+k);
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
}
}
}
}
I think you get confused by the console output.
The important part is if every .get()
in the consumer gets all the elements from the producer.
When you remove all the confusing System.out.
lines and just use
class Consumer implements Runnable {
Holder h;
public Consumer(Holder h) {
this.h = h;
}
public void run() {
for (int i = 0; i < 1000; i++) {
int k = h.get();
if (k != i)
System.out.println("Got wrong value " + k + "expected value " + i);
}
}
}
You will see that your code works fine.
I think your confusion comes from outputs that looks like this
Getting : 990
Putting : 993
Getting : 991
Getting : 992
The thread Consumer Going ta sleep...
Getting : 993
But also you see all the get
s are in the right order and all the put
s too.
So this is a problem of the way in which the output works in Java, when multiple threads are involved.