在同步控制方法或同步控制块里调用wait()notify()notifyAll()。如果在非同步控制方法里调用这些方法,程序能通过编译,但运行的时候,将得到IllegalMonitorStateException异常,并伴随着一些含糊的消息,比如"当前线程不是拥有者"。消息的意思是,调用wait()notify()notifyAll()的线程在调用这些方法前必须"拥有"对象的锁。当前的线程不是此对象锁的所有者,却调用该对象的notify()notify()wait()方法时抛出该异常。

  wait/notfiy 一定要在同步代码块里,并且持有相同的对象锁;

package com.xiaoye;

/** * @Description : * @Author : ChenYao * @Version : 1.0 * @Create : 2019/6/8 23:15 * @Update : 2019/6/8 23:15 * @see : */
public class ThreadProviderConsumerDemo {
    public static void main(String[] args) {
        Person person = new Person();
        //false生產;true消费;
        person.flag = false;
        Provider provider = new Provider(person);
        Consumer consumer = new Consumer(person);
        provider.start();
        consumer.start();
    }
}

class Provider extends Thread {
    Person person;

    public Provider(Person person) {
        this.person = person;
    }

    @Override
    public void run() {
        int count = 0;
        while (true) {
            synchronized (person) {
                if (person.flag) {
                    try {
                        person.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (count == 0) {
                    person.name = "小花";
                    person.sex = "女";
                } else {
                    person.name = "小明";
                    person.sex = "男";
                }
                count = (count + 1) % 2;
                person.flag = true;
                person.notify();
            }
        }
    }
}

class Consumer extends Thread {
    Person person;

    public Consumer(Person person) {
        this.person = person;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (person) {
                if (person.flag) {
                    System.out.println(person);
                    person.flag = false;
                    person.notify();
                }
                try {
                    person.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

class Person {
    public String name;
    public String sex;
    public boolean flag;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        StringBuffer stringBuffer = new StringBuffer();
        return stringBuffer
                .append("Person:[name=")
                .append(name)
                .append(",sex=")
                .append(sex + ",flag=" + flag + "]")
                .toString();
    }
}

Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]
Person:[name=小明,sex=]
Person:[name=小花,sex=]