java notifyAll:illegalMonitorStateException

java notifyAll:illegalMonitorStateException,java,multithreading,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 hung

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

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();
    }
}

所以我在类mother中notifyAll()的行中得到了一个“线程中的异常”main“java.lang.IllegalMonitorStateException”。我不知道发生了什么事,有人能帮我吗?

因为妈妈做完饭后,你需要通知孩子们。现在,您正在对mom对象本身调用notifyAll(),该对象在功能上看起来不正确。一种方法是将子对象引用传递给Mom,并在Mom完成烹饪后通知他们,因为您需要在Mom完成烹饪后通知子对象。现在,您正在对mom对象本身调用notifyAll(),该对象在功能上看起来不正确。一种方法是将子对象引用传递给Mom,并在Mom完成烹饪后通知他们。请考虑以下几点

  • 您必须使用一个公共对象来保护所有需要互斥的代码块
  • 只有当对象的监视器被当前线程锁定时,才能对其调用wait/notify
  • 要获取监视器,线程必须进入一个由拥有监视器的对象保护的块。JVM在内部使用监视器
  • 除此之外,还可以使用

    请参见下面的代码

    synchronized void method1 () {
    }
    
    synchronized void method2() {
    }
    
    这里
    method1
    method2
    将由调用它们的对象的监视器进行保护。因此,如果我们想在一个受保护的区块内使用相同的监视器,将按照以下步骤进行

    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.
    

    考虑以下几点

  • 您必须使用一个公共对象来保护所有需要互斥的代码块
  • 只有当对象的监视器被当前线程锁定时,才能对其调用wait/notify
  • 要获取监视器,线程必须进入一个由拥有监视器的对象保护的块。JVM在内部使用监视器
  • 除此之外,还可以使用

    请参见下面的代码

    synchronized void method1 () {
    }
    
    synchronized void method2() {
    }
    
    这里
    method1
    method2
    将由调用它们的对象的监视器进行保护。因此,如果我们想在一个受保护的区块内使用相同的监视器,将按照以下步骤进行

    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.
    

    wait and notify只能在受保护的块中调用,请查看此链接是否需要直接使用wait and notifyAll?如果不是,我建议“java.util.concurrent.Semaphore”。您需要捕获Mom类中的子对象,然后通知它们wait和notify只能在受保护的块中调用,请查看此链接是否需要直接使用wait和notifyAll?如果不是,我建议“java.util.concurrent.Semaphore”。您需要捕获Mom类中的子对象,然后通知它们