According to How to use wait and notify in Java? I have to synchronized on the same object to call notify.
I have synchronized on the same haveCoffee object. Why I am getting IllegalMonitorStateException when I call the notify method ?
I am Sleeping
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at com.example.concurrent.basic.WaitAndNotify$2.run(WaitAndNotify.java:42)
in the following code:
public class WaitAndNotify {
public static void main(String[] args) {
Thread haveCoffee = new Thread() {
public void run() {
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("I am awake and ready to have coffee");
}
}
};
Thread me = new Thread() {
public void run() {
synchronized (haveCoffee) {
try {
System.out.print("I am Sleeping");
Thread.sleep(4000);
notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
haveCoffee.start();
me.start();
}
}
On the first Thread, you call wait on an object while having its monitor (the object being this haveCoffee).
However, on the second thread, you call notify() on me, while having the monitor of haveCoffee.
This should work:
public class WaitAndNotify {
public static void main(String[] args) {
final Thread haveCoffee = new Thread() {
public void run() {
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("I am awake and ready to have coffee");
}
}
};
Thread me = new Thread() {
public void run() {
synchronized (haveCoffee) {
try {
System.out.print("I am Sleeping");
Thread.sleep(4000);
haveCoffee.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
haveCoffee.start();
me.start();
}
}
From oracle documentation page,
public class IllegalMonitorStateException
extends RuntimeException
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
Whenever you get this exception, just go through your code and check wait() and notify() calls and the object on which these calls have been invoked. You can easily figure out what went wrong.
EDIT:
wait() or notify() calls have to be invoked on object once you get monitor on that object.
You should be calling
haveCoffee.notify()
instead of just
notify().
If you invoke just notify() it calls the notify() method on the this object which is the second thread me where as you have synchronized on haveCoffee thread and that is the reason for exception you are seeing.
So the code in thread2 me should looks like:
synchronized (haveCoffee) {
try {
System.out.print("I am Sleeping");
Thread.sleep(4000);
haveCoffee.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Related
I am new to Java multithreading. I created simple producer-consumer pattern using wait and notify but my producer is getting called only once in tbe starting.
public class ThreadApp {
public static void main(String[] args) throws InterruptedException {
ProducerConsumerWorldp = new ProducerConsumerWorld();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
class ProducerConsumerWorld{
public void producer() throws InterruptedException{
synchronized (this) {
while(true){
System.out.println("Producer thread started running");
wait();
System.out.println("Resumed Producing");
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(true){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
notify();
Thread.sleep(2000);
System.out.println("consumed all");
}
}
}
}
I am creating separate threads for producer and consumer. Producer thread only gets called in the starting and then after it is never getting executed.
I tried two option to overcome this issue. first I put while condition outside of synchronized block second is given below.
class ProducerConsumerWorld{
public void producer() throws InterruptedException{
synchronized (this) {
while(true){
System.out.println("Producer thread started running");
notify();
wait();
System.out.println("Resumed Producing");
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(true){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
notify();
Thread.sleep(2000);
System.out.println("consumed all");
wait();
}
}
}
}
Both works great. Which one the of the appropriate solution to use ? I am still unable to figure out why the code I put in question is not working properly.
I am still unable to figure out why the code I put in question is not working properly
The wait() in producer() releases the monitor which allows consumer() to enter its synchronized block. Then the wait() in producer() starts waiting till consumer() calls notify() and releases the monitor (i.e. exits its synchronized block). You never exit synchronized in consumer() therefore the wait() in producer() is blocked forever
I am still unable to figure out why the code I put in question is not
working properly
I've managed to fix your code, and I've attached below the fixed code snippet.
I've introduced a boolean instance variable named isConsumed for the ProducerConsumerWorld. In doing so, what essentially happens is that after Producer Thread produces, he updates the state of isConsumed to false, since he has produced something which is yet to be consumed. Afterwards, the producer notifies the the Consumer thread, that Producer has finished producing. Next, it invokes wait() on the ProducerConsumerWorld which releases Producer's lock on ProducerConsumerWorld. Then, it waits for the lock on ProducerConsumerWorld.
Meanwhile, the Consumer Thead acquires the lock on ProducerConsumerWorld, which allows it to enter the consumer method, where it checks if there is produce yet to be consumed. If so, it consumes and updates the isConsumed variable to true, and notifies the produce has been consumed. Then the consumer proceeds to releases its lock on ProducerConsumerWorld by calling wait(), and waits to reacquire the lock on ProducerConsumerWorld after Producer has consumed.
Note:
Calling notify() doesn't release a lock until the thread moves out of the synchronized block, or wait() is called, thus releasing the lock.
Source: Oracle's OCA/OCP Java SE 7 Study Guide Page 760
Code:
import java.util.Scanner;
public class ThreadApp {
public static void main(String[] args) throws InterruptedException {
ProducerConsumerWorld p = new ProducerConsumerWorld();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
class ProducerConsumerWorld{
boolean consumed = false;
public void producer() throws InterruptedException{
System.out.println("Producer thread started running");
synchronized (this) {
while(this.consumed == true){ // Consumer has consumed and is waiting for produce
System.out.println("Resumed Producing");
this.consumed = false;
notify();
wait();
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(this.consumed == false){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
this.consumed = true;
System.out.println("consumed all");
notify();
wait();
}
}
}
}
This gives me an output like,
Below is the consumer producer problem code, but the code is not working as expected. Here the consumer and producer are supposed to be just producing and consuming one object.
public class ProducerConsumer {
private static LinkedList<Integer> linkedList = new LinkedList<>();
public static void main(String a[]) throws InterruptedException {
Thread producer = new Thread(new Runnable() {
#Override
public void run() {
synchronized(this) {
while (linkedList.size() == 1) {
try {
wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Produced");
linkedList.add(1);
notify();
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread consume = new Thread(new Runnable() {
#Override
public void run() {
// produce
synchronized(this) {
while (linkedList.isEmpty()) {
try {
wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Consumed");
linkedList.removeFirst();
notify();
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
});
producer.start();
consume.start();
producer.join();
consume.join();
}
}
We get the output as : Produced
And the program hangs.
Please help with possible solutions/ explanations
Use a shared lock. In the posted code each Runnable is using itself as a lock so no actual locking takes place.
When a thread waits, another thread needs to call notify on the same lock in order to wake up the waiting thread. We know from your logging that the Producer thread does its thing, but since the notify acts on a lock that is not the same as the one the Consumer is using, the consumer thread never wakes up.
Changing the code to use a shared lock works:
import java.util.*;
public class ProducerConsumer { private static LinkedList linkedList = new LinkedList();
public static void main(String a[]) throws InterruptedException {
final Object lock = new Object();
Thread producer = new Thread(new Runnable() {
#Override
public void run() {
synchronized (lock) {
while (linkedList.size() ==1) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Produced");
linkedList.add(1);
lock.notify();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
Thread consume = new Thread(new Runnable() {
#Override
public void run() {
// produce
synchronized (lock) {
while (linkedList.isEmpty()) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Consumed");
linkedList.removeFirst();
lock.notify();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
producer.start();
consume.start();
producer.join();
consume.join();
}
}
Output for this is:
c:\example>java ProducerConsumer
Produced
Consumed
which I think is what you're expecting.
Btw see this other answer I wrote for a dirt-simple implementation of a queue; you are better off protecting the shared data structure than putting the code in the threads accessing the data structure, especially look at how much easier the code is to write.
Concurrency means that you can not know before runtime which Thread will end first. So you can not know which of the Consumer and Producer is launched, executed or finished first.
To help you, you can use a cyclic barrier https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html or applying the Fork/Join Framework https://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html
Your synchronized blocs just say : only one Thread at a time can execute this part of code, not execute the first and the second after.
An example of how CyclicBarrier works :
service = Executors.newFixedThreadPool(numThreadsTotal);
CyclicBarrier c = new CyclicBarrier(numThreadsToWait);
runProducer();
c.await();
runConsumer();
It will wait until the there is as much Threads as numThreadsToWait that have execute the runProducer to execute the runConsumer().
Perhaps using a Thread Pool with a size of 1 could help you, but you will loose the benefits of concurrency.
I think best what you can do, is use BlockingQueue.
I have created an java thread and passed an stack reference to it's constructor,
which initialize thread stack reference.
In run method i have created an synchronized block with that stack object,
the moment am calling wait in run inside synchronized block , i am getting IllegalMonitorStateException.
Thread Class :
public class Producer extends Thread {
Stack<String> stack=null;
public Producer(Stack<String> stack) {
this.stack=stack;
}
#Override
public void run() {
synchronized (stack) {
if(stack.isEmpty()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Main Class:
public class MainClass {
public static void main(String[] args) {
Stack<String> stack=new Stack<String>();
Producer p=new Producer(stack);
p.start();
}
}
Output :
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at demo.Producer.run(Producer.java:20)
For wait() (or notify()) to work, you must call it on the same object. What you have now is the same as
synchronized (stack) {
if(stack.isEmpty()){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
instead you should do
synchronized (stack) {
if(stack.isEmpty()){
try {
stack.wait(); // wait on the same object synchronized.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Note: as wait can wake spuriously you have do this in a loop or your method could return prematurely.
synchronized (stack) {
while (stack.isEmpty()){
try {
stack.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class firstThread extends Helper1
{
Thread thread_1 = new Thread(new Runnable()
{
#Override
public void run() {
try {
for (int i = 1; i <= 20; i++) {
System.out.println("Hello World");
Thread.sleep(500);
if (i == 10) {
Notify();
Wait();
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
class secondThread extends firstThread
{
Thread thread_2 = new Thread(new Runnable()
{
#Override
public void run() {
// TODO Auto-generated method stub
try {
Wait();
for(int i = 1; i<=20; i++)
{
System.out.println("Welcome");
Thread.sleep(100);
}
Notify();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
class Helper1
{
public synchronized void Wait() throws InterruptedException
{
wait();
}
public synchronized void Notify() throws InterruptedException
{
notify();
}
}
public class InheritanceClass {
public static void main(String[] args)
{
Thread f = new Thread(new firstThread().thread_1);
Thread s = new Thread(new secondThread().thread_2);
f.start();
s.start();
}
}
Only the first Thread has an output. Please try my code. I don't know why it happens.
The second thread does not give output, I suppose it's because of Wait() in the secondThread, I don't know what to do.
The problem is with the following code:
class Helper1
{
public synchronized void Wait() throws InterruptedException
{
wait();
}
public synchronized void Notify() throws InterruptedException
{
notify();
}
}
Above, the wait() and notify() calls are equivalent to this.wait() and this.notify(). However, thread1 and thread2 are separate objects so they are not ever going to communicate via this method.
In order for communication to occur, you need a shared lock object. For example:
Object lock = new Object();
firstThread = new firstThread(lock);
secondThread = new secondThread(lock);
and synchronizations like:
void wait(Object lock) {
synchronized(lock) {
lock.wait();
}
}
void notify(Object lock) {
synchronized(lock) {
lock.notify();
}
}
Disclaimer: I would never do this personally, however it does answer the OP's question.
This code is really confusing, which is making it hard to see the underlying problem.
You should never start a class with a lower-case letter since it makes it look like a method/field name (e.g. firstThread).
I'm pretty sure Wait and Notify have no reason to be synchronized.
Why does secondThread inherit from firstThread??? Actually, why do you have those two classes at all? You should just make an anonymous inner class from Helper1 or something.
Anyway, the problem is that when you call Notify() in thread1 it notifies itself, not thread2.
class myThreadRun implements Runnable
{
public void run() {
roo();
}
public synchronized void roo()
{
System.out.println("In thread before wait " + Thread.currentThread().getName());
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JOptionPane.showMessageDialog(null, "After wait in\n"+Thread.currentThread().getName());
System.out.println("In thread after wait " + Thread.currentThread().getName());
//notify();
}
public synchronized void foo()
{
notify();
}
}
public class ThreadingDemo {
public synchronized void Start()
{
System.out.println("Labamba");
myThreadRun mThRun = new myThreadRun();
Thread thread = new Thread(mThRun);
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//mThRun.foo(); //This works
//mThRun.notify(); //crash
//thread.notify();//crash
try {
thread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
new ThreadingDemo().Start();
}
This is simple code to demonstrate wait() and notify(),
In the myThreadRun class run() method just does wait() and foo() method does notify()
as indicated in the code above, if I do mThRun.notify() the program crashes, but mThRun.foo() runs the without a hitch and gives the much needed result. I need to know why?
You need to own the monitor for the object to all obj.wait() and obj.notify().
That is why it works when called within the synchronized block on mThRun but not outside. So if you put the mThRun.notify(); in a synchronized block, it works, like this:
synchronized (mThRun) {
mThRun.notify();
}
In your case you are getting an IllegalMonitorStateException.
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
Put another way, you don't hold the lock of the object you are trying to notify. Having the lock of a different object doesn't help.
When you use notify() and wait() you need to change a state and check for it. If you don't do this, you can find that either
notify() is called before wait() and the signal is lost
wait() wakes prematurely
You cannot assume notify/wait is a reliable messaging protocol.
I suggest you consider using the concurrency library which is a better choice in most cases from Java 5.0 (2004)
May be you are going very hard with wait/notify. Its very simple. what you need to know is which object is used for monitor lock. To make the same code working i have modified the same code: ( I have put MAK comment where i changed the code, hope its helpful)
class MyThreadRun implements Runnable {
public void run() {
roo();
}
public synchronized void roo() {
System.out.println("In thread before wait " + this);
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
JOptionPane.showMessageDialog(null, "After wait in\n" + Thread.currentThread().getName());
System.out.println("In thread after wait " + Thread.currentThread().getName());
}
}
public class ThreadingDemo {
public static void main(String[] args) {
MyThreadRun mThRun = new MyThreadRun();
System.out.println("Labamba: " +mThRun);
Thread thread = new Thread(mThRun);
thread.start();
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
//mThRun.foo(); //This works //MAK: no sense
//mThRun.notify(); //crash //MAK: Need monitor lock
synchronized (mThRun) {
mThRun.notify();//crash //MAK: will work now
}
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}