在同步控制方法或同步控制块里调用wait(),notify()和notifyAll()。如果在非同步控制方法里调用这些方法,程序能通过编译,但运行的时候,将得到IllegalMonitorStateException异常,并伴随着一些含糊的消息,比如"当前线程不是拥有者"。消息的意思是,调用wait(),notify()和notifyAll()的线程在调用这些方法前必须"拥有"对象的锁。当前的线程不是此对象锁的所有者,却调用该对象的notify(),notify(),wait()方法时抛出该异常。
生产者线程
publicclassProducer implementsRunnable{
private List<Product> list;
public Producer(List<Product> list) {
this.list = list;
}
@Override
publicvoid run() {
if(list.size()>=10){
try{
System.out.println("库存已满,等待消费者消费");
list.wait();
}catch (Exception e) {
e.printStackTrace();
}
}else{
list.add(new Product());
System.out.println("生产者生产一个产品");
list.notifyAll();
}
}
}
消费者线程:
publicclass Connsumer implements Runnable{
private List<Product> list;
public Connsumer(List<Product> list) {
this.list = list;
}
@Override
publicvoid run() {
if(list.size()== 0){
try{
System.out.println("产品被全部消费,等待生产者生产!");
list.wait();
}catch (Exception e) {
e.printStackTrace();
}
}else{
System.out.println("消费者消费一个产品");
list.remove(0);
list.notifyAll();
}
}
}
主函数:
publicclass Test {
publicstaticvoidmain(String[] args) {
List<Product>list = newArrayList<Product>();
Producer pro = new Producer(list);
Connsumer con = new Connsumer(list);
for(int i = 0;i<=10;i++){
newThread(pro).start();
newThread(con).start();
}
}
}
运行结果:
Exception in thread "Thread-4" Exception in thread"Thread-0" java.lang.IllegalMonitorStateException
产品被全部消费,等待生产者生产!
生产者生产一个产品
生产者生产一个产品
生产者生产一个产品
生产者生产一个产品
生产者生产一个产品
生产者生产一个产品
消费者消费一个产品
消费者消费一个产品
消费者消费一个产品
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:503)
atcom.yhd.conandpro.Connsumer.run(Connsumer.java:16)
atjava.lang.Thread.run(Unknown Source)
Exception in thread "Thread-3" java.lang.IllegalMonitorStateException
消费者消费一个产品
消费者消费一个产品
atjava.lang.Object.notifyAll(NativeMethod)
atcom.yhd.conandpro.Connsumer.run(Connsumer.java:24)
at java.lang.Thread.run(UnknownSource)
Exception in thread "Thread-11" java.lang.IllegalMonitorStateException
atjava.lang.Object.notifyAll(NativeMethod)
atcom.yhd.conandpro.Connsumer.run(Connsumer.java:24)
atjava.lang.Thread.run(Unknown Source)
Exception in thread "Thread-9" java.lang.IllegalMonitorStateException
atjava.lang.Object.notifyAll(NativeMethod)
atcom.yhd.conandpro.Connsumer.run(Connsumer.java:24)
atjava.lang.Thread.run(Unknown Source)
Exception in thread "Thread-5" java.lang.IllegalMonitorStateException
atjava.lang.Object.notifyAll(NativeMethod)
atcom.yhd.conandpro.Connsumer.run(Connsumer.java:24)
atjava.lang.Thread.run(Unknown Source)
生产者生产一个产品
生产者生产一个产品
Exception in thread "Thread-14" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
atcom.yhd.conandpro.Producer.run(Producer.java:25)
atjava.lang.Thread.run(Unknown Source)
Exception in thread "Thread-7" java.lang.IllegalMonitorStateException
atjava.lang.Object.notifyAll(NativeMethod)
at com.yhd.conandpro.Connsumer.run(Connsumer.java:24)
at java.lang.Thread.run(Unknown Source)
原因:在调用list对象锁的的时候,程序并没有锁住list对象。让另一个对象执行某种操作以维护其自己的锁,就必须先得到对象的锁。
所以可以将程序修改为:
生产者线程:
publicclass Producer implements Runnable{
private List<Product> list;
public Producer(List<Product> list) {
this.list = list;
}
@Override
publicvoid run() {
if(list.size()>=10){
try{
System.out.println("库存已满,等待消费者消费");
synchronized (list) {
list.wait();
}
}catch (Exception e) {
e.printStackTrace();
}
}else{
list.add(new Product());
System.out.println("生产者生产一个产品");
synchronized(list) {
list.notifyAll();
}
}
}
}
消费者线程:
publicclass Connsumer implements Runnable{
private List<Product> list;
public Connsumer(List<Product> list) {
this.list = list;
}
@Override
publicvoid run() {
if(list.size()== 0){
try{
System.out.println("产品被全部消费,等待生产者生产!");
synchronized(list) {
list.wait();
}
}catch (Exception e) {
e.printStackTrace();
}
}else{
System.out.println("消费者消费一个产品");
list.remove(0);
synchronized(list) {
list.notifyAll();
}
}
}
}