等待唤醒机制

等待唤醒机制

这是多个线程间的一种协作机制。谈到线程我们经常想到的是线程间的竞争(race),比如去争夺锁,但这并不是 故事的全部,线程间也会有协作机制。就好比在公司里你和你的同事们,你们可能存在在晋升时的竞争,但更多时 候你们更多是一起合作以完成某些任务。 就是在一个线程进行了规定操作后,就进入等待状态(wait()), 等待其他线程执行完他们的指定代码过后 再将 其唤醒(notify());在有多个线程进行等待时, 如果需要,可以使用 notifyAll()来唤醒所有的等待线程。

wait/notify 就是线程间的一种协作机制。

被通知线程也不能立即恢复执行,因为它当初中断的地方是在同步块内,而 此刻它已经不持有锁,所以她需要再次尝试去获取锁(很可能面临其它线程的竞争),成功后才能在当初调 用 wait 方法之后的地方恢复执行。

1. wait:线程不再活动,不再参与调度,进入 wait set 中,因此不会浪费 CPU 资源,也不会去竞争锁了,这时 的线程状态即是 WAITING。它还要等着别的线程执行一个特别的动作,也即是“通知(notify)”在这个对象 上等待的线程从wait set 中释放出来,重新进入到调度队列(ready queue)中

2. notify:则选取所通知对象的 wait set 中的一个线程释放;例如,餐馆有空位置后,等候就餐最久的顾客最先 入座。

3. notifyAll:则释放所通知对象的 wait set 上的全部线程。

一个等待唤醒的例子:

BaoZi类
1 public class BaoZi {
2     String pier;
3     String xianer;
4     boolean flag = false;//包子资源 是否存在 包子资源状态
5 }
View Code
ChiHuo类
 1 public class ChiHuo extends Thread {
 2     private BaoZi bz;
 3 
 4     public ChiHuo(String name, BaoZi bz) {
 5         super(name);
 6         this.bz = bz;
 7     }
 8 
 9     @Override
10     public void run() {
11         while (true) {
12             synchronized (bz) {
13                 System.out.println(bz);
14                 if (bz.flag == false) {//没包子
15                     try {
16                         bz.wait();
17                     } catch (InterruptedException e) {
18                         e.printStackTrace();
19                     }
20                 }
21                 System.out.println("吃货正在吃" + bz.pier + bz.xianer + "包子");
22                 bz.flag = false;
23                 bz.notify();
24             }
25         }
26     }
27 }
View Code
BaoZiPu类
 1 package com.fan;
 2 
 3 public class BaoZiPu extends Thread {
 4     private BaoZi bz;
 5 
 6     public BaoZiPu(String name, BaoZi bz) {
 7         super(name);
 8         this.bz = bz;
 9     }
10 
11     @Override
12     public void run() {
13         int count = 0;
14         //造包子
15         while (true) {
16             //同步
17             synchronized (bz) {
18                 System.out.println(bz);
19                 if (bz.flag == true) {//包子资源 存在
20                     try {
21                         bz.wait();
22                     } catch (InterruptedException e) {
23                         e.printStackTrace();
24                     }
25                 }
26                 // 没有包子 造包子
27                 System.out.println("包子铺开始做包子");
28                 if (count % 2 == 0) {
29                     // 冰皮 五仁
30                     bz.pier = "冰皮";
31                     bz.xianer = "五仁";
32                 } else {
33                     // 薄皮 牛肉大葱
34                     bz.pier = "薄皮";
35                     bz.xianer = "牛肉大葱";
36                 }
37                 count++;
38                 bz.flag = true;
39                 System.out.println("包子造好了:" + bz.pier + bz.xianer);
40                 System.out.println("吃货来吃吧");
41                  //唤醒等待线程 (吃货)
42                 bz.notify();
43             }
44         }
45     }
46 }
View Code
测试类
 1 public class Demo {
 2     public static void main(String[] args) {
 3 //等待唤醒案例
 4         BaoZi bz = new BaoZi();
 5         ChiHuo ch = new ChiHuo("吃货", bz);
 6         BaoZiPu bzp = new BaoZiPu("包子铺", bz);
 7         ch.start();
 8         bzp.start();
 9     }
10 }
View Code

 

posted @ 2019-07-11 09:34  穿靴子的猫o_O  阅读(208)  评论(0编辑  收藏  举报