黑马程序员技术交流社区

标题: 线程错误 [打印本页]

作者: 傅荣康    时间: 2011-8-1 20:45
标题: 线程错误
public class Exercise {
public static void main(String[] args) {
  Exercise ex=new Exercise();
  ex.go();
}
public void go(){
  MyThread mt=new MyThread("one");
  mt.start();
}
}

class MyThread extends Thread{
private String name="";
MyThread(String s){
  name=s;
}
public void run(){
  notwait();  
  System.out.println("finished");
}
public void notwait(){
  while(true){
   try{
    System.out.println("waiting");
    wait();
   }
   catch(InterruptedException e){}
   System.out.println(name);
  }
}
}
这段程序运行后结果为
waiting
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at mypackage.MyThread.notwait(Exercise.java:34)
at mypackage.MyThread.run(Exercise.java:24)
请问导致此异常的具体原因。非常感谢!
作者: 李龙    时间: 2011-8-1 21:26
不知道你的程序要做什么用, 不过IllegalMonitorStateException是因为你的wait()少添加了一个监听,
在wait()改成
  1. synchronized(this)
  2. {
  3.         wait();
  4. }
复制代码
就行了。
myeclipse下右键→Surround With里面有直接加监听的代码。
[ 本帖最后由 李龙 于 2011-08-01  21:27 编辑 ]
作者: 詹季春    时间: 2011-8-2 01:51
对于Object类提供的wait()notify()、notifyAll()这三个方法必须要由同步监视器对象来调用的,这可以分为两种情况:
1、对于使用synchronized修饰的方法,因为该类的默认实例this就是同步监视器,所以可以在同步方法中直接使用这三个方法[code=java]public synchronized void draw(double drawAmount)
        {
                try
                {
                        //如果flag为假,表明账户中还没有人存钱进去,则取钱方法阻塞
                        if (!flag)
                        {
                                wait();
                        }
                        else
                        {
                                //执行取钱
                                System.out.println(Thread.currentThread().getName() +
                                        " 取钱:" +  drawAmount);
                                balance -= drawAmount;
                                System.out.println("账户余额为:" + balance);
                                //将标识账户是否已有存款的旗标设为false。
                                flag = false;
                                //唤醒其他线程
                                notifyAll();
                        }
                }
                catch (InterruptedException ex)
                {
                        ex.printStackTrace();
                }
        }[/code]2、对于使用synchronized修饰的同步代码块,同步监视器是synchronized后面括号里面的对象,所以必须使用这个对象调用这三个方法:[code=java]public  void draw(double drawAmount)
        {
                synchronized(account)
                        try
                        {
                                //如果flag为假,表明账户中还没有人存钱进去,则取钱方法阻塞
                                if (!flag)
                                {
                                        account.wait();
                                }
                                else
                                {
                                        //执行取钱
                                        System.out.println(Thread.currentThread().getName() +
                                                " 取钱:" +  drawAmount);
                                        balance -= drawAmount;
                                        System.out.println("账户余额为:" + balance);
                                        //将标识账户是否已有存款的旗标设为false。
                                        flag = false;
                                        //唤醒其他线程
                                        account.notifyAll();
                                }
                        }
                        catch (InterruptedException ex)
                        {
                                ex.printStackTrace();
                        }
                }
        }[/code]




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2