关于java的wait()的问题

weidu23 2013-08-20 08:03:25
首先请看代码:

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异常呢 ?

我初学多线程,求指教!
...全文
146 10 打赏 收藏 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
weidu23 2013-08-21
  • 打赏
  • 举报
回复
引用 9 楼 e274794140 的回复:
哦,那是因为 this.wait();等待后没有线程去唤醒它,它就会一直等在那
的确是这样 !!!O(∩_∩)O~
马达马达达 2013-08-20
  • 打赏
  • 举报
回复
哦,那是因为 this.wait();等待后没有线程去唤醒它,它就会一直等在那
weidu23 2013-08-20
  • 打赏
  • 举报
回复
引用 5 楼 A280104758 的回复:
顶一个顶一个
谢了
weidu23 2013-08-20
  • 打赏
  • 举报
回复
引用 3 楼 u011467227 的回复:
虽然看不懂但是还是给你顶一下
谢了
weidu23 2013-08-20
  • 打赏
  • 举报
回复
引用 2 楼 e274794140 的回复:
这杨写法是给方法上锁,默认锁是this。所以这里this.notify就不报错了
自己解决了 ...
weidu23 2013-08-20
  • 打赏
  • 举报
回复
引用 2 楼 e274794140 的回复:
......


按照你这个思路,的确,可以运行,
但是,我注意到,线程一直没有释放,不知道这是为什么。
请看,如图:


不知怎么回事 ?能否指教下 。
另外,怎么释放掉这个线程 ?
u011467227 2013-08-20
  • 打赏
  • 举报
回复
虽然看不懂但是还是给你顶一下
马达马达达 2013-08-20
  • 打赏
  • 举报
回复
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就不报错了
weidu23 2013-08-20
  • 打赏
  • 举报
回复
之前发帖说错了一句话, ----------------------------- 这个代码中,抛的异常也是我自定义的,比如上面报错中java.lang.IllegalMonitorStateException: c , 这里的c 是发生异常时所运行的线程!!! 也就是说,在c线程运行时,发生了异常,这正是我自定义异常的目的! ----------------------------- 我指的是,我就是想,出现异常时,找到是哪个线程发生的异常!

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧