java notifyAll:illegalMonitorStateException

时间:2016-01-03 08:43:55

标签: java multithreading

我想模拟一位母亲叫三个孩子吃晚饭,这是我的代码:

class child extends Thread{
    String name;
    mother mom;
    public child(mother mon, String name){
        this.name = name;
        this.mom = mom;
    }

    public void run(){
        System.out.println(name+" is hungry.");
        while (!mom.finished){
            try {
                wait();
            }catch(InterruptedException e){}
        }
        washhands();
    }

    public synchronized void washhands(){
        System.out.println(name+" washed hands.");
        notifyAll();
    }
}

class mother{
    boolean finished;

    public mother(){
        finished = false;
    }
    public void cook(){
        System.out.println("Mom started cooking.");
        try{
            Thread.sleep(200);
        }catch(InterruptedException e){};
        finished = true;
        System.out.println("Mom finished cooking.");
        notifyAll();
    }
}

public class work{
    public static void main(String[] args){
        mother mom = new mother();
        child Alex = new child(mom, "Alex");
        child James = new child(mom, "James");
        child Tod = new child(mom, "Tod");

        Alex.start();
        James.start();
        Tod.start();
        mom.cook();
    }
}

所以我在线程" main"中得到了一个"异常java.lang.IllegalMonitorStateException"在班级母亲的notifyAll()行。我不知道会发生什么,有人可以帮助我吗?

2 个答案:

答案 0 :(得分:0)

一旦妈妈完成烹饪,你需要通知孩子。现在你在mom对象本身上调用notifyAll(),它看起来功能不正确。一种方法是将子对象引用传递给Mom,并在妈妈完成烹饪后通知他们

答案 1 :(得分:0)

考虑以下几点。

  1. 您必须使用公共对象来保护所有需要互斥的代码块。
  2. 只有当某个对象的监视器被当前线程锁定时才能调用它。
  3. 要获取监视器,线程必须进入由拥有监视器的对象保护的块。监视器由JVM内部使用。
  4. 除了使用Java naming conventions.

    命名您的类和变量

    请参阅以下代码

    synchronized void method1 () {
    }
    
    synchronized void method2() {
    }
    

    此处method1method2将由将要调用它们的对象的监视器守护。因此,如果我们想在一个受保护的区域内使用相同的监视器,它将按如下方式完成。

    public void method3() {
        synchronized(this) {
        }
        ...
    }
    

    现在method1()method2()method3()中的防护块将受到同一个对象监视器的保护。

    如果我们需要跨类保护块,那么我们需要在它们之间共享一个共同的对象。我在下面的代码中进行了相同的修改。

    package filevisitor;
    
    import java.util.Random;
    import java.util.concurrent.atomic.AtomicLong;
    
    class child extends Thread{
        String name;
        volatile mother mom;
        public child(mother mom, String name){
            this.name = name;
            this.mom = mom;
        }
    
        public void run(){
            System.out.println(name+" is hungry.");
            while (!mom.finished){
                try {
                    synchronized(work.myLockObject) {
                        work.myLockObject.wait();
                    }
                }catch(InterruptedException e){}
            }
            washhands();
        }
    
        public void washhands(){
            System.out.println(name+" washed hands.");
            synchronized(work.myLockObject) {
                work.myLockObject.notifyAll();
            }
        }
    }
    
    class mother{
        boolean finished;
    
        public mother(){
            finished = false;
        }
        public void cook(){
            System.out.println("Mom started cooking.");
            try{
                Thread.sleep(200);
            }catch(InterruptedException e){};
            finished = true;
            System.out.println("Mom finished cooking.");
            synchronized(work.myLockObject) {
                work.myLockObject.notifyAll();
            }
        }
    }
    
    public class work{
        public static final Object myLockObject = new Object();
        public static void main(String[] args){
            mother mom = new mother();
            child Alex = new child(mom, "Alex");
            child James = new child(mom, "James");
            child Tod = new child(mom, "Tod");
    
            Alex.start();
            James.start();
            Tod.start();
            mom.cook();
        }
    }
    

    儿童班this.mom = mom;还有一个小错误。参数名称为mon,因此此分配无效,导致NullPointerException

    <强>输出

    Mom started cooking.
    Alex is hungry.
    Tod is hungry.
    James is hungry.
    Mom finished cooking.
    Tod washed hands.
    James washed hands.
    Alex washed hands.