线程间的通讯等待唤醒机制

概念:多个线程在处理同一个资源 但是处理的动作 (线程的任务)却不相同

比如:线程A用来生产包装的 线程B用来吃包子的 包子可以理解为同一资源 线程A于线程B处理的动作 一个是生产

一个是消费 那么线程A与线程B之间就存在线程通信问题

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

等待唤醒机制

这是多个线程间的一种协作机制 线程我们想到的时线程间的竞争(race) 比如去争同步锁 但是者并不是故事的全部 线程间也会有协作机制

就是在一个线程进行了规定操作后 就进入等待状态 等待其他线程执行完他们的指定代码过后 再将其他线程执行完他们的指定代码过后 再将其他唤醒 再多个线程进行等待时 如果需要 可以使用

  1. 调用wait方法的前提是获得这个对象的锁(synchronized对象锁,如果有多个线程取竞争这个锁,只有一个线程获得锁,其他线程会处于等待队列)
  2. 使当前执行代码的线程进行等待 . ( 把线程放到等待队列中 )
  3. 调用wait方法会释放锁
  4. 满足一定条件会重新尝试获得这个锁,被唤醒的之后不是立即恢复执行,而是进入阻塞队列,竞争锁

结束等待的三个方式

  1. 1.其他线程调用该对象的 notify 方法.
  2. 2.wait 等待时间超时 (wait 方法提供一个带有 timeout 参数的版本, 来指定等待时间).
  3. 3.其他线程调用该等待线程的 interrupted 方法, 导致 wait 抛出 InterruptedException 异常

等待唤醒中的方法

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

  1. notify
  2. notify()随机唤醒一个处在等待状态的线程  
  3. notifyAll()唤醒所有处在等待状态的线程

方法notify()也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的 其它线程,对其发出通知notify,并使它们重新获取该对象的对象锁。

如果有多个线程等待,则有线程调度器随机挑选出一个呈 wait 状态的线程。(并没有 "先来后到") 在notify()方法后,当前线程不会马上释放该对象锁,要等到执行notify()方法的线程将程序执行完,也就是退出同步代码块之后才会释放对象锁。

  •  案例分析:
/*/
        线程共有资源对象---->包子
 */
public class BaoZi {

    String Name;
    boolean flag;

}
/*
 *       消费者模型
 * */
public class ChiHuo extends Thread {
    BaoZi baoZi;//共享资源对象

    //定义构造方法:给线程定义名字,同时给Baozi对象赋值
    public ChiHuo(String threadName, BaoZi baoZi) {
        super(threadName);
        this.baoZi = baoZi;
    }

    /*/
        吃货线程功能:
            如果包子不存在   线程进入等待状态
            如果包子存在,    线程开始吃包子,吃完后更改包子的状态变为状态不存在,唤醒早餐店线程开始制作包子
     */
    @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();
                    }

                }
            }
        }
    }
}
package com.hp.text09;

public class ZaoCanDian extends Thread {
    BaoZi baoZi;//资源对象

    //定义构造方法:给线程定义名字,同时给Baozi对象赋值
    public ZaoCanDian(String threadName, BaoZi baoZi) {
        super(threadName);
        this.baoZi = baoZi;
    }
    /*
     *   早餐店县城功能:
     *           如果包子存在,     线程进入等待状态
     *           如果包子不存在,    线程开始制作包子,制作完成更改包子状态为存在,唤醒吃货线程吃包子
     * */

    @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();//唤醒同一个资源下的其他线程
                }
            }
        }
    }
}
package com.hp.text09;

public class ThreadText1 {
    public static void main(String[] args) {
        BaoZi baoZi=new BaoZi();
        baoZi.Name="韭菜鸡蛋盒子";
        baoZi.flag=false;

        ChiHuo chiHuo=new ChiHuo("猪八戒",baoZi);
        ZaoCanDian zaoCanDian=new ZaoCanDian("春光灿烂早餐店",baoZi);

        chiHuo.start();
        zaoCanDian.start();
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值