Reputation: 11
I'm not getting expected result for below program, I was expecting both producer and consumer method should execute in some sequence, but for some reason only producer method is getting executed.
I have two question here :
Joining both thread together in last line of main method is working properly, I'm not able to understand difference between both.
public class ProducerConsumer {
List<Integer> data = new ArrayList<>();
synchronized void produce() throws InterruptedException {
for (int i = 0; i < 10; i++) {
System.out.println("Producing");
data.add(i);
}
wait();
}
synchronized void consume() throws InterruptedException {
System.out.println("Consuming");
data.clear();
notify();
}
public static void main(String[] args) throws InterruptedException {
ProducerConsumer pc = new ProducerConsumer();
Runnable r2 = ()-> {
try {
pc.produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Thread thread1 = new Thread(r2);
thread1.start();
thread1.join();
Runnable r1 = () -> {
try {
pc.consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Thread thread = new Thread(r1);
thread.start();
thread.join();
}
Output : Producing Producing Producing Producing Producing Producing Producing Producing Producing Producing
Upvotes: 0
Views: 50
Reputation: 27210
1) A notify()
call does not do anything at all. Unless some other thread is already waiting to be notified.
It's up to you to guarantee that any time one of your threads calls wait()
, some other thread will notify()
the same object some time after the wait()
has begun.
Oracle's Guarded Blocks Tutorial does a pretty good job of explaining exactly how o.wait()
and o.notify()
work, and it explains how to establish that guarantee.
2) There is virtually no reason to do this:
Thread t = new Thread(r);
t.start();
t.join();
Your program will use less CPU, and it will use less memory, and it will accomplish exactly the same thing if you just call r.run()
instead. The entire point of threads is to allow different things to happen concurrently, and there is no concurrency if one thread joins
a new thread immediately after creating it. The new Thread
object is wasted unless you do something like this with it:
Thread t = new Thread(r);
t.start();
doSomethingElseWhileThread_t_isRunning();
t.join();
3) wait()
and notify()
are a very low-level means of communicating between threads. Your code will be easier to read and understand if you use higher-level synchronization objects that are built on top of wait()
and notify()
instead of directly
calling them.
A java.util.concurrent.ArrayBlockingQueue
instance would be especially well suited to a "producer/consumer" application.
Upvotes: 0
Reputation: 692201
The produce()
method ends with wait()
. So it blocks until some thread notifies it.
The only thread that does that is the consumer thread. But the consumer thread is started by the main method only after the producer thread has ended. And it can't end until it's been notified. So you have a deadlock.
If you join()
only after the two threads are started, then the consumer thread can start without having to wait for the producer thread to be finished. That still doesn't make the program correct since
Upvotes: 1