Reputation: 7145
import java.util.LinkedList;
import java.util.Queue;
class Producer extends PubSub implements Runnable{
@Override
public void run() {
synchronized(queue){
if (queue.size() == 99){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.add(2);
try{
Thread.sleep(1000);
}
catch (InterruptedException e){
e.printStackTrace();
}
notify();
}
}
}
class Consumer extends PubSub implements Runnable{
@Override
public void run() {
synchronized(queue){
if(queue.isEmpty()){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(queue.poll());
}
}
}
public class PubSub {
static Integer QUEUE_SIZE = 100;
Queue<Integer> queue = new LinkedList<Integer>();
public static void main(String[] args) {
Producer producer = new Producer();
Consumer consumer = new Consumer();
Thread producerThread = new Thread(producer);
Thread consumerThread = new Thread(consumer);
producerThread.start();
consumerThread.start();
System.out.println("Started both the threads");
}
}
I am getting a java.lang.IllegalMonitorStateException
in the wait()
part. I want to know what I am doing wrong here. Any ideas??
The complete exception that I get is as follows.
Exception in thread "Thread-1" Started both the threads
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at Consumer.run(PubSub.java:36)
at java.lang.Thread.run(Thread.java:745)
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at Producer.run(PubSub.java:23)
at java.lang.Thread.run(Thread.java:745)
Upvotes: 6
Views: 720
Reputation: 101
A thread can call notify() or wait() only on an object on which it has already acquired lock. In your program thread has lock on queue object and then your thread is calling wait on this.
Upvotes: 0
Reputation: 2468
I think that I got your code working ...
As stated by JB Nizet you have to invoke wait and notify on the queue
object.
I think that such object must be declared static
to be shared by Producer and Consumer.
I have included while loops for the code to continue running until the end of time.
Also, an extra notify
is needed before Producer and Consumer first wait
Here is your code with that changes included:
import java.util.LinkedList;
import java.util.Queue;
class Producer extends PubSub implements Runnable{
@Override
public void run() {
int index = 0;
while (true) {
synchronized(queue){
while (queue.size() == QUEUE_SIZE){
try {
System.out.println("Producer waits");
queue.notify();
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Produce element " + (++index));
queue.add(2);
queue.notify();
try {
Thread.sleep(1000);
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
}
class Consumer extends PubSub implements Runnable{
@Override
public void run() {
while (true) {
synchronized(queue) {
while (queue.isEmpty()){
try {
System.out.println("Consumer waits");
queue.notify();
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Consume element " + queue.poll());
queue.notify();
}
}
}
}
public class PubSub {
static Integer QUEUE_SIZE = 100;
static Queue<Integer> queue = new LinkedList<Integer>();
public static void main(String[] args) {
Producer producer = new Producer();
Consumer consumer = new Consumer();
Thread producerThread = new Thread(producer);
Thread consumerThread = new Thread(consumer);
producerThread.start();
consumerThread.start();
System.out.println("Started both the threads");
}
}
Upvotes: 2
Reputation: 3031
Check out the Javadoc for IllegalMonitorStateException
https://docs.oracle.com/javase/7/docs/api/java/lang/IllegalMonitorStateException.html
The exception is thrown when you attempt to wait()
(or notify()
) on an object of which you don't hold the monitor; You have synchronized on queue, but attempted to wait()
on this
, which is not the queue, rather the runnable.
Changing wait()
to queue.wait()
and notify()
to queue.notify()
should work.
Upvotes: 3
Reputation: 691775
You're calling wait()
, which is equivalent to this.wait()
, but you're not holding the monitor of this
. You're holding the monitor on queue
. So it should be queue.wait()
. (same for notify()
).
Upvotes: 6