I am doing classic Producer-Consumer problem in Java using low level synchronization and wait() and notify(). I know there are better implementations using structures from java.util.concurrent package but my problem revolves around low level implementation:
private static ArrayList<Integer> list = new ArrayList<Integer>();
static Object obj = new Object();
public static void producer() throws InterruptedException {
synchronized (obj) {
while (true) {
if (list.size() == 10) {
System.out.println("Queue full.. Waiting to Add");
obj.wait();
} else {
int value = new Random().nextInt(100);
if (value <= 10) {
Thread.sleep(200);
System.out.println("The element added was : " + value);
list.add(value);
obj.notify();
}
}
}
}
}
public static void consumer() throws InterruptedException {
synchronized (obj) {
while (true) {
Thread.sleep(500);
if (list.size() == 0) {
System.out.println("Queue is empty...Waiting to remove");
obj.wait();
} else {
System.out.println("The element removed was : "
+ list.remove(0));
obj.notify();
}
}
}
}
There are 2 threads in the program, 1 each for producer and consumer specifically. The code works just fine.
The only issue is that producer goes on to produce messages until the maximum at once (until size is 10 for the list), and consumer consumes all 10 at once.
How can I make producer and consumer work at the same time?
This is the sample output:
The element added was : 4
The element added was : 0
The element added was : 0
The element added was : 4
The element added was : 3
The element added was : 1
The element added was : 10
The element added was : 10
The element added was : 3
The element added was : 9
Queue full.. Waiting to Add
The element removed was : 4
The element removed was : 0
The element removed was : 0
The element removed was : 4
The element removed was : 3
The element removed was : 1
The element removed was : 10
The element removed was : 10
The element removed was : 3
The element removed was : 9
Queue is empty...Waiting to remove
Edit: Here is the corrected code:
private static ArrayList<Integer> list = new ArrayList<Integer>();
private static Object obj = new Object();
public static void producer() throws InterruptedException {
while (true) {
Thread.sleep(500);
if (list.size() == 10) {
System.out.println("Waiting to add");
synchronized (obj) {
obj.wait();
}
}
synchronized (obj) {
int value = new Random().nextInt(10);
list.add(value);
System.out.println("Added to list: " + value);
obj.notify();
}
}
}
public static void consumer() throws InterruptedException {
while (true) {
Thread.sleep(500);
if (list.size() == 0) {
System.out.println("Waiting to remove");
synchronized (obj) {
obj.wait();
}
}
synchronized (obj) {
int removed = list.remove(0);
System.out.println("Removed from list: " + removed);
obj.notify();
}
}
}
You can not run two thread in synchronized block with same object. When one method is running another method can not run until another thread call
wait
method.To solve this problem you should just put
add
andremove
in synchronized block. For more information see this.class Resources {
}
class MyThread5 extends Thread {
}
public class ProducerConsumerExample {
}
Don't use
list.size() == 10
, instead you can checklist.size == 1
.For producer produced, one wait for the other one till consumer consumes. Refer this Producer Consumer Problem - Solution using wait and notify In Java
Producer and Consumer problem is the classic example of multiple-process synchronization problem. This describes two process, producer and consumer which share the common resources, buffer. Producer job is to generate data and put it into a buffer and consumer job is consume the generated data and remove from the buffer.
Producer must ensure that no element should be added when buffer is full, it should call
wait()
until consumer consume some data andnotify
to the producer thread AND consumer must ensure that it should not try to remove item from buffer when it is already empty, it should callwait()
which simply waits until producer generate data and add it into buffer and notify to the consumer usingnotify
ornotifyAll
.This problem can be solved using
BlockingQueue
interface which do manage this producer and consumer implementation own.Output: