线程间通信机制(等待唤醒机制),生产者消费者模型的案例代码

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

二:

等待唤醒中的方法
等待唤醒机制就是用于解决线程间通信的问题的,使用到的3个方法的含义如下
1.wait: 线程不再活动,不再参与调度,进入 wait set 中,因此不会浪费CPU 资源,也不会去竞争锁了,这时的线程状态即是 WAITING。它还要等着别的线程执行一个特别的动作,也即是”通知(notify)”在这个对象上等待的线程从wait set 中释放出来,重新进入到调度队列 (ready queue)中
2.notify: 则选取所通知对象的 wait set 中的一个线程释放:例如,馆有空位置后,等候就最久的顾客最先入座。
3.notifyAll : 则释放所通知对象的 wait set 上的全部线程

三:

调用wait和notify方法需要注意的细节
1.wait方法与notify方法必须要由同一个锁对象调用。因为:对应的锁对象可以通过notiy唤醒使用同一个锁对象调用的wait方法后的线程。
2.wait方法与notifv方法是属于Obiect类的方法的。因为:锁对象可以是任意对象,而任意对象的所属类都是继承了Obiect类的。
3.wait方法与notify方法必须要在同步代码块或者是同步函数中使用。因为:必须要通过锁对象调用这2个方法。

生产者和消费者 

 

首先要新建4个类。
生产线程的类(包子铺类)
消费线程的类(顾客的类)
包子类(作为线程安全的锁对象)同时调用等待唤醒方法也要用到这个类

消费品 

public class BaoZi {
  // 包子的名称
  String name;
  // 包子是否存在
  boolean flag;
}

吃包子类 


public class ChiHuo extends Thread{
  //资源对象
  BaoZi baoZi;
  // 定义构造方法;给线程定义名字,同事给BaoZi对象赋值
  public ChiHuo(String threadName,BaoZi bz){
      super(threadName);
      this.baoZi = bz;
  }
 
//吃货线程的功能:
//如果包子不存在     线程进入等待状态
//如果包子存在       线程开始吃包子,吃完后更改包子的状态变为不存在,唤醒包子店线程开始制作    //包子
  @Override
  public void run(){
     String threadName = Thread.currentThread().getName();
     for(int i = 0 ; i<10;i++){
         synchronized (baoZi){
             // 包子存在
             if(baoZi.flag){
                 // 吃包子
                 System.out.println(threadName+"正在吃"+baoZi.name);
                 // 更改包子状态
                 baoZi.flag=false;
                 // 唤醒同一资源下的其他线程
                 baoZi.notify();
             }else{
                 try{
                     baoZi.wait();
                 }catch (InterruptedException e){
                     e.printStackTrace();
                 }
             }
         }
      }
  }
}

 做包子类以及测试类


public class ZaoCanDian extends Thread{
  //资源对象
  BaoZi baoZi;
  //定义构造方法
  public ZaoCanDian(String threadName,BaoZi bz){
      super(threadName);
      this.baoZi = bz;
  }
//早餐店线程功能: 
//如果包子存在    线程进入等待状态
//如果包子不存在   线程开始制作包子,制作完毕更改包子状态为存在,唤醒吃货线程吃包子
  @Override
  public void run(){
     String threadName = Thread.currentThread().getName();
     for(int i = 0 ; i< 10;i++){
         synchronized (baoZi){
             // 包子存在
             if(baoZi.flag){
                 try{
                     baoZi.wait();
                 }catch (InterruptedException e){
                     e.printStackTrace();
                 }
             }else{
                 System.out.println(threadName+"制作"+baoZi.name);
                 // 更改包子状态
                 baoZi.flag = true;
                 // 唤醒同一资源下的其它线程
                 baoZi.notify();
              }
         }
     }
  }
  public static void main(String[] args) {
     BaoZi bz = new BaoZi();
     // 包子名称
     bz.name="包子";
     // 包子初始状态
     bz.flag=false;
     // 消费者名称
     ChiHuo ch = new ChiHuo("猪八戒",bz);
     // 生成者名称
     ZaoCanDian zcd = new ZaoCanDian("春光早餐",bz);
     // 启动线程
     ch.start();
     zcd.start();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值