我试图深入了解wait()和notify()的概念。 为此,我编写了一个非常简单的程序,其中:
这是代码:
package com.company;
public class Wait {
public static void main(String[] args) throws InterruptedException {
Resource resource = new Resource();
Thread consumerThread = new Thread(new Runnable() {
@Override
public void run() {
try {
resource.consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread producerThread = new Thread() {
@Override
public void run() {
try {
resource.produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
producerThread.start();
consumerThread.start();
}
}
class Resource {
String commonResource = new String();
public void consume() throws InterruptedException {
System.out.println("In consume. Outside Sync block: " + Thread.currentThread().getName());
synchronized (commonResource) {
System.out.println("In consume. Inside Sync block" + Thread.currentThread().getName());
commonResource.wait();
System.out.println(commonResource);
}
}
public void produce() throws InterruptedException {
System.out.println("In Produce. Outside Sync block: " + Thread.currentThread().getName());
// So that consumer executes first
Thread.sleep(1000L);
synchronized (commonResource) {
System.out.println("In produce. Inside sync block: " + Thread.currentThread().getName());
commonResource = "I am not empty now";
System.out.println("Done production. I am now freeing up the resource");
commonResource.notifyAll();
}
}
}
执行后,出现以下异常,代码挂起:
In consume. Outside Sync block: Thread-0
In consume. Inside Sync blockThread-0
In Produce. Outside Sync block: Thread-1
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at com.company.Resource.produce(Wait.java:55)
at com.company.Wait$2.run(Wait.java:23)
In produce. Inside sync block: Thread-1
Done production. I am now freeing up the resource
根据notifyAll的Java文档,执行notifyAll()
时,监视器与其他线程一起运行。
但是从日志中以及根据我的理解可以看出,{-1}是{-1}的监视器的所有者,也是线程1在notifyAll()
上调用的。
所以,我的问题是,为什么在这种情况下会抛出IllegalMonitorStateException? 我在了解这一点上缺少什么吗?
谢谢。
答案 0 :(得分:0)
正如@JBNizet所说,您更改了用作锁定的String
值。这就是为什么您得到IllegalMonitorStateException
的原因。要摆脱这种情况,可以像这样对final
使用单独的Object
锁synchronization
,
class Resource {
private final Object lock = new Object();
String commonResource = new String();
public void consume() throws InterruptedException {
System.out.println("In consume. Outside Sync block: " + Thread.currentThread().getName());
synchronized (lock) {
System.out.println("In consume. Inside Sync block" + Thread.currentThread().getName());
lock.wait();
System.out.println(commonResource);
}
}
public void produce() throws InterruptedException {
System.out.println("In Produce. Outside Sync block: " + Thread.currentThread().getName());
// So that consumer executes first
Thread.sleep(1000L);
synchronized (lock) {
System.out.println("In produce. Inside sync block: " + Thread.currentThread().getName());
commonResource = "I am not empty now";
System.out.println("Done production. I am now freeing up the resource");
lock.notifyAll();
}
}
}