读书人

关于java的wait()的有关问题

发布时间: 2013-08-24 13:17:55 作者: rapoo

关于java的wait()的问题
首先请看代码:


package clone;

/**
* 生产者与消费者的问题
*/
import java.util.*;
public class Run{
public static void main(String[]args){
Producer p = new Producer();
Consumer c = new Consumer();
new Thread(p,"p").start();//start时就会调用produce()
new Thread(c,"c").start();//start时就会调用consumption()
}
}

class Producer implements Runnable{
public Producer(){
if( null == goods ) goods = new ArrayList<Goods>();
}
@Override
public void run(){
try{
synchronized(Run.class){
if( 5 > goods.size() )
for( int i=goods.size() ; i<5 ; i++)
produce();
}
}
catch(Exception err){err.printStackTrace();}
}
public void produce() throws Exception{//生产
System.out.println("coming ! the current thread is "+Thread.currentThread().getName());
int size = goods.size()+1 ;
String name = String.valueOf(size);
goods.add(new Goods(size , name ,Double.parseDouble(name))) ;
}
private static List<Goods> goods;
public static List<Goods> obtainedGoods(){
System.out.println(Thread.currentThread().getName()+":"+goods.size());return goods ; }
}

class Consumer implements Runnable{
@Override
public void run(){
try{
synchronized(Run.class){
goods = Producer.obtainedGoods();
if( null == goods ) System.out.println(Thread.currentThread().getName()+":"+"do not have this kind of goods !");
if( 0 == goods.size() )
{
System.out.println(Thread.currentThread().getName()+":"+"this goods have been done not have ! we must wait for produce");
this.wait();
}
consumption();
this.notify();
}
}
catch(Exception err){
err = new IllegalMonitorStateException(Thread.currentThread().getName());
err.printStackTrace();
}
}
public void consumption() throws Exception{//消费
System.out.println("coming ! the current thread is "+Thread.currentThread().getName());
Goods g;
int i = goods.size() ;
while( 0 != i ){
g = (Goods)goods.get(i-1);


g.displays();
i -- ;
}
}
private List<Goods> goods;
}

class Goods{//商品类
private int id ;
private String name = "goods";
private double price ;
public Goods(int id , String name , double price){this.id = id ; this.name = this.name+name ; this.price = price ;}
public void displays(){//显示商品
System.out.println(Thread.currentThread().getName()+":"+"id="+id+", name="+name+", price"+price);
}
}



以上代码会报错,报错说是:
java.lang.IllegalMonitorStateException: c
at clone.Consumer.run(Run.java:59)
at java.lang.Thread.run(Thread.java:619)

这个代码中,抛的异常也是我自定义的,比如上面报错中java.lang.IllegalMonitorStateException: c ,
这里的c 是发生异常时所运行的线程!!!

也就是说,在c线程运行时,发生了异常,这正是我自定义异常的目的!

--------------------------------------------
然而,问题却来了:
JDK1.6所述:
wait()、notify()必须:当前线程必须拥有此对象监视器
IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。

我在Consumer类中写的wait()和notify()方法!线程c就是Consumer的对象c对应的那个线程!!!
那么,wait() notify()方法就应该是在本对象的监视器范围内 !!!
既然如此,怎么会抛出IllegalMonitorStateException异常呢 ?

我初学多线程,求指教!
[解决办法]
public void run(){
try{
synchronized(Run.class){
goods = Producer.obtainedGoods();
if( null == goods ) System.out.println(Thread.currentThread().getName()+":"+"do not have this kind of goods !");
if( 0 == goods.size() )
{
System.out.println(Thread.currentThread().getName()+":"+"this goods have been done not have ! we must wait for produce");


this.wait();
}
consumption();
this.notify();//这里抛异常
}
}
catch(Exception err){
err = new IllegalMonitorStateException(Thread.currentThread().getName());
err.printStackTrace();
}
}


这里synchronize代码块的锁是Run.class(即所谓的监视器)
根据api,notify()的调用者就得是synchroize代码块的锁,不然就抛异常。这里要写成Run.class.notify()就行了。
或者上面的方法写成
public synchronized void run(){
try{
goods = Producer.obtainedGoods();
if( null == goods ) System.out.println(Thread.currentThread().getName()+":"+"do not have this kind of goods !");
if( 0 == goods.size() )
{
System.out.println(Thread.currentThread().getName()+":"+"this goods have been done not have ! we must wait for produce");
this.wait();
}
consumption();
this.notify();
}
catch(Exception err){
err = new IllegalMonitorStateException(Thread.currentThread().getName());
err.printStackTrace();
}

这杨写法是给方法上锁,默认锁是this。所以这里this.notify就不报错了
[解决办法]
虽然看不懂但是还是给你顶一下
[解决办法]
该回复于2013-08-21 08:40:30被管理员删除

读书人网 >J2SE开发

热点推荐