等待唤醒机制


等待唤醒机制

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

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


一、等待唤醒中的方法

等待唤醒机制就是用于解决线程间通信的问题的,使用到的3个方法的含义如下︰

  • wait :线程不再活动,不再参与调度,进入wait set中,因此不会浪费CPU资源,也不会去竞争锁了,这时的线程状态即是WAITING。它还要等着别的线程执行一个特别的动作,也即是"通知( notify ) "在这个对象上等待的线程从wait set中释放出来,重新进入到调度队列( ready queue )中
  • notify :则选取所通知对象的wait set 中的一个线程释放﹔例如,餐馆有空位置后,等候就餐最久的顾客最先入座。
  • notifyAll :则释放所通知对象的wait set 上的全部线程。

二、包子铺案例

1.代码如下

Baozi实体类代码如下(示例):

/**
 * 功能描述:包子实体类
 *
 * @Author: wang
 * @Date: 2022/4/29 22:32
 */
public class Baozi {
    private String pi;
    private String xian;
    private boolean flag = false;// 判断有没有包子,默认没有:false

    public Baozi(String pi, String xian, boolean flag) {
        this.pi = pi;
        this.xian = xian;
        this.flag = flag;
    }

    public Baozi() {
    }

    public String getPi() {
        return pi;
    }

    public void setPi(String pi) {
        this.pi = pi;
    }

    public String getXian() {
        return xian;
    }

    public void setXian(String xian) {
        this.xian = xian;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}

Bao_ZP线程类代码如下(示例):

import java.util.Date;

/**
 * 功能描述:包子铺生产包子
 *
 * @Author: wang
 * @Date: 2022/4/29 22:34
 */
public class Bao_ZP extends Thread {
    private Baozi bz;

    public Bao_ZP(Baozi bz) {
        this.bz = bz;
    }

    @Override
    public void run() {
        synchronized (bz) {
            int count=0;
            while (true) {
                if (bz.isFlag() == false) {
                    System.out.println("包子没货需要生产!!!");
                    try {
						// 交替生产两种馅的包子。
                        if (count % 2 == 0) {
                            bz.setPi("白皮");
                            bz.setXian("绿馅");
                        } else {
                            bz.setPi("黑皮");
                            bz.setXian("红馅");
                        }
                        Date date = new Date();
                        System.out.println("包子铺正在生产" + bz.getPi() + bz.getXian() + "的包子,请稍等!");
                        System.out.println("...");
                        bz.wait(5000);/*假设生产包子需要五秒钟*/
                        System.out.println("包子铺" + bz.getPi() + bz.getXian() + "的包子,生产好了!");
                        bz.setFlag(true);
                        count++;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        bz.notify();
                    }

                } else {
                    try {
                    //有包子不需要生产,归还cpu进入等待状态
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }


        }
    }
}

Chi_bz线程类代码如下(示例):

/**
 * 功能描述:顾客吃包子
 *
 * @Author: wang
 * @Date: 2022/4/29 23:14
 */
public class Chi_bz extends Thread{
    private Baozi bz;

    public Chi_bz(Baozi bz) {
        this.bz = bz;
    }

    @Override
    public void run() {
        synchronized (bz){
            while (true){
                if (bz.isFlag()==true){
                    System.out.println("顾客买到包子了,开始吃包子");
                    System.out.println("...");
                    try {
                    // 假设吃包子需要五秒钟。
                        bz.wait(5000);
                        System.out.println("包子吃完了");
                        // 更改包子状态,没有包子了:false
                        bz.setFlag(false);
                        System.out.println("**********************************************");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                    // 释放线程。
                        bz.notify();
                    }
                }else {
                    try {
                    // 没有包子,进入等待状态,等包子铺做。
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

TreadTest线程测试类代码如下(示例):

/**
 * 功能描述:测试启动做包子线程和吃包子线程
 *
 * @Author: wang
 * @Date: 2022/4/29 22:59
 */
public class TreadTest {
    public static void main(String[] args) {
        Baozi baozi = new Baozi();
        Bao_ZP bao_zp = new Bao_ZP(baozi);
        Chi_bz chi_bz = new Chi_bz(baozi);
        chi_bz.start();
        bao_zp.start();

    }
}

2.运行结果

结果如下(示例):

包子没货需要生产!!!
包子铺正在生产白皮绿馅的包子,请稍等!
...
包子铺白皮绿馅的包子,生产好了!
顾客买到包子了,开始吃包子
...
包子吃完了
**********************************************
包子没货需要生产!!!
包子铺正在生产黑皮红馅的包子,请稍等!
...
包子铺黑皮红馅的包子,生产好了!
顾客买到包子了,开始吃包子
...
包子吃完了
**********************************************

注意:为了测试运行结果使用了while(true){}设置为死循环。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值