等待与唤醒机制

Posted lxy522

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了等待与唤醒机制相关的知识,希望对你有一定的参考价值。

等待与唤醒机制

1、线程间通信

概念:多线程在处理同一个资源,但是处理的动作却不相同。

技术图片

为什么处理线程间通信?

多线程并发执行时,在默认情况下CPU是随机切换线程的,当我们需要多线程来共同完成一件任务,并且我们希望他们有规律的执行,那么多线程之间需要一些协调通信,以此来帮我们达到多线程共同操作一份数据。

如何保证线程间通信有效利用资源?

多线程在处理同一个资源,并且任务不同时,需要线程通信来帮忙解决线程间对同一变量的使用或操作。就是多线程在操作同一份数据时,避免对同一共享变量的争夺。也就是我们需要通过一定的手段使各个线程能有效利用资源。而这种手段即——等待唤醒机制。

2、等待唤醒机制

概念:这是多线程间的协作机制。谈到线程我们经常想到的是线程间的竞争,比如去争夺锁,但这并不是故事的全部,线程间也会有协作机制。就好比在公司里你和你的同事们,你们可能存在晋升的竞争,但更多时候你们更多是一起合作完成某些任务。

就是在一个线程金信诺过了规定操作后,就进入等待状态(wait()),等待其他线程执行完他们的指定代码过后再将其唤醒(notify());在有多个线程进行等待时,如果需要,可以使用notify All()来唤醒所有的等待线程。wait/notify就是线程间的一种协作机制。

技术图片

等待唤醒中的方法:

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

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

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

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

技术图片

技术图片

技术图片

包子类:

public class BaoZi {
  private String pi;
  private String xian;
  private boolean flag;
?
  public BaoZi() {
  }
?
  public BaoZi(String pi, String xian, boolean flag) {
      this.pi = pi;
      this.xian = xian;
      this.flag = flag;
  }
?
  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;
  }
}

包子铺:

public class BaoZiPu implements Runnable {
  private BaoZi bz;
?
  public BaoZiPu() {
  }
?
  public BaoZiPu(BaoZi bz) {
      this.bz = bz;
  }
?
  //生产包子
  @Override
  public void run() {
      int count = 0;
      while (true){
          synchronized (bz){
              //对包子的状态进行判断
              if (bz.isFlag()){
                  //包子铺调用wait方法进入等待状态,让客人吃包子
                  try {
                      bz.wait();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
              //被唤醒之后执行,包子铺生产包子
              if (count%2==0){
                  bz.setPi("薄皮");
                  bz.setXian("三鲜");
              }else{
                  bz.setPi("厚皮");
                  bz.setXian("牛肉大葱");
              }
              count++;
              System.out.println("包子铺正在生产:"+bz.getPi()+bz.getXian()+"包子");
              //生产包子
              try {
                  Thread.sleep(3000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              //包子好了后,修改状态
              bz.setFlag(true);
              bz.notify();//唤醒客人的线程
              System.out.println("包子生产完毕");
          }
      }
  }
}

客人:

public class ChiHuo implements Runnable {
  private BaoZi baoZi;
?
  public ChiHuo() {
  }
?
  public ChiHuo(BaoZi baoZi) {
      this.baoZi = baoZi;
  }
?
  public BaoZi getBaoZi() {
      return baoZi;
  }
?
  public void setBaoZi(BaoZi baoZi) {
      this.baoZi = baoZi;
  }
?
  @Override
  public void run() {
      while (true){
          synchronized (baoZi){
              if(baoZi.isFlag()==false){
                  //客人等待包子做好
                  try {
                      baoZi.wait();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
              //唤醒之后,吃包子
              System.out.println("吃"+baoZi.getPi()+baoZi.getXian()+"的包子");
              baoZi.setFlag(false);//包子吃完了
              baoZi.notify();//唤醒去做包子
              System.out.println("包子吃完了");
          }
      }
  }
}

测试:

public class Demo05Main {
  public static void main(String[] args) {
      //创建包子对象
      BaoZi baoZi = new BaoZi();
?
      BaoZiPu baoZiPu = new BaoZiPu(baoZi);
      new Thread(baoZiPu).start();
      ChiHuo chiHuo = new ChiHuo(baoZi);
      new Thread(chiHuo).start();
  }
}

 

以上是关于等待与唤醒机制的主要内容,如果未能解决你的问题,请参考以下文章

线程系列三线程的等待与唤醒机制

14 进程的等待与唤醒机制

等待与唤醒机制

阶段1 语言基础+高级_1-3-Java语言高级_05-异常与多线程_第4节 等待唤醒机制_7_等待唤醒机制需求分析

等待唤醒机制

买卖包子案例——等待唤醒机制