等待-通知机制定义解释:
当线程不满足执行条件时,线程进入等待阶段,当条件满足后时,通知线程并唤醒它继续执行,这就时等待-唤醒机制。
Java中的等待唤醒机制实现:
Synchronized来实现等待-通知机制,Java 语言内置的 synchronized 配合 wait()、notify()、notifyAll() 这三个方法实现等待-通知机制。
完整的等待-通知机制实现,线程获取互斥锁,当线程要求的条件不满足,释放互斥锁,进入等待状态,当要求的条件满足,通知等待的线程,重新获取互斥锁。
这个总结恰如其分的总结出线程协作的本质,对与线程协作的设计,我认同书上说的一句话:协作的核心是想清楚协作的共享变量和条件是什么

public class test6 {
    public static void main(String[] args) {
        waitthread waitthread = new waitthread();
        System.out.println("等待线程启动");
        waitthread.start();
        System.out.println("通知线程启动");
        waitthread.fire();
    }

    public static class waitthread extends Thread {

        private volatile boolean fire = false;

        @Override
        public synchronized void run() {
            while (!fire) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("收到通知后打印消息");
        }

        public synchronized void fire() {
            this.fire = true;
            notify();
        }
    }


}

输出结果:
等待线程启动
通知线程启动
收到通知后打印消息

Process finished with exit code 0

使用以上三种方法可以完成多种场景的线程同步问题,下面介绍5种场景如下:
1.生产者/消费者模型
2.同时开始模型
3.主从协作模型
4.主从异步结果协作模型
5.集合点模型
实践是检验真理的唯一标准,以下是代码例子:
1.生产者/消费者模型实践

public class test7 {

    public static class MyBlockingQuene {
        private volatile int j = 1;
        private volatile boolean fire = false;


        public synchronized void put() {
            while (!fire) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            int i = 0;
            while (i < 4 && j < 101) {
                System.out.println("线程1打印:" + j);
                j++;
                i++;
            }
            fire = false;
            notifyAll();

        }

        public synchronized void take() {
            while (fire) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            int i = 0;
            while (i < 4 && j < 101) {
                System.out.println("线程2打印:" + j);
                j++;
                i++;
            }
            fire = true;
            notifyAll();
        }
    }

    public static class Producer extends Thread {
        MyBlockingQuene myBlockingQuene;

        public Producer(MyBlockingQuene myBlockingQuene) {
            this.myBlockingQuene = myBlockingQuene;
        }

        @Override
        public void run() {
            while (myBlockingQuene.j < 101) {
                myBlockingQuene.put();
            }
        }
    }

    public static class Consumer extends Thread {
        MyBlockingQuene myBlockingQuene;

        public Consumer(MyBlockingQuene myBlockingQuene) {
            this.myBlockingQuene = myBlockingQuene;
        }

        @Override
        public void run() {
            while (myBlockingQuene.j < 101) {
                myBlockingQuene.take();
            }
        }
    }

    public static void main(String[] args) {
        MyBlockingQuene myBlockingQuene = new MyBlockingQuene();
        new Producer(myBlockingQuene).start();
        new Consumer(myBlockingQuene).start();

    }
}

线程1和线程2交替打印数字,本质上就是生产者和消费者模型,线程1生产5个数字,然后通知线程2生产5个数字,直到这个数字到达100
线程2打印:1
线程2打印:2
线程2打印:3
线程2打印:4
线程1打印:5
线程1打印:6
线程1打印:7
线程1打印:8
线程2打印:9
线程2打印:10
线程2打印:11
线程2打印:12
线程1打印:13
线程1打印:14
线程1打印:15
线程1打印:16
线程2打印:17
线程2打印:18
线程2打印:19
线程2打印:20
线程1打印:21
线程1打印:22
线程1打印:23
线程1打印:24
线程2打印:25
线程2打印:26
线程2打印:27
线程2打印:28
线程1打印:29
线程1打印:30
线程1打印:31
线程1打印:32
线程2打印:33
线程2打印:34
线程2打印:35
线程2打印:36
线程1打印:37
线程1打印:38
线程1打印:39
线程1打印:40
线程2打印:41
线程2打印:42
线程2打印:43
线程2打印:44
线程1打印:45
线程1打印:46
线程1打印:47
线程1打印:48
线程2打印:49
线程2打印:50
线程2打印:51
线程2打印:52
线程1打印:53
线程1打印:54
线程1打印:55
线程1打印:56
线程2打印:57
线程2打印:58
线程2打印:59
线程2打印:60
线程1打印:61
线程1打印:62
线程1打印:63
线程1打印:64
线程2打印:65
线程2打印:66
线程2打印:67
线程2打印:68
线程1打印:69
线程1打印:70
线程1打印:71
线程1打印:72
线程2打印:73
线程2打印:74
线程2打印:75
线程2打印:76
线程1打印:77
线程1打印:78
线程1打印:79
线程1打印:80
线程2打印:81
线程2打印:82
线程2打印:83
线程2打印:84
线程1打印:85
线程1打印:86
线程1打印:87
线程1打印:88
线程2打印:89
线程2打印:90
线程2打印:91
线程2打印:92
线程1打印:93
线程1打印:94
线程1打印:95
线程1打印:96
线程2打印:97
线程2打印:98
线程2打印:99
线程2打印:100

Process finished with exit code 0