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

线程间的等待与唤醒机制,wait和notify是Object的方法,用于线程的等待与唤醒,必须搭配着synchronized来使用,脱离 synchronized 使用 wait 会直接抛出异常

为什么要处理线程间通信:

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

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

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

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

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

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

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

等待唤醒中的方法
等待唤醒机制就是用于解决线程之间通信的问题 使用到的3个方法的含义如下:notify
notify()随机唤醒一个处在等待状态的线程  
notifyAll()唤醒所有处在等待状态的线程
方法notify()也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的 其它线程,对其发出通知notify,并使它们重新获取该对象的对象锁。

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

 案例

包子铺:

package KeTangTest.XianChengTongXun;
 
/*
 资源类对象:多个线程共同操作的对象
*/
 
public class BaoZi {
    String name;    //包子名称
    boolean flag;   //包子的状态,(true表示存在,false表示不存在)
}

吃货:

package KeTangTest.XianChengTongXun;
 
public class ChiHuo extends Thread{
    BaoZi baoZi;
    //构造方法:用来指定线程的名字和要操作的资源
    public ChiHuo(String name,BaoZi bz){
        super(name);
        this.baoZi=bz;
    }
 
    /**
     * 对于吃货-----消费者:
     * 如果包子 不存在    进入等待状态
     * 如果包子 存在     进入执行状态,吃包子。吃完之后包子变为不存在  此时唤醒早餐店制作包子
     */
 
 
    @Override
    public void run() {
        String threadName=Thread.currentThread().getName();
        int count=0;
        while (true){
            synchronized (baoZi){
                count++;
                if (count>10){
                    break;
                }
                if (baoZi.flag){ //如果包子存在
                    System.out.println(threadName+"开始吃"+baoZi.name); //吃包子
                    baoZi.flag=false; //修改状态
                    baoZi.notify(); //唤醒同一资源下的其他线程
                }else {
                    try {
                        baoZi.wait(); //进入等待状态
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

早餐店:

package KeTangTest.XianChengTongXun;
 
public class ZaoCanDian extends Thread{
    BaoZi baoZi;
    //构造方法:用来指定线程的名字和要操作的资源
    public ZaoCanDian(String name,BaoZi bz){
        super(name);
        this.baoZi=bz;
    }
    /**
     * 对于早餐店------生产者
     * 如果包子 不存在     进入执行状态,制造包子。  制作完毕包子存在,唤醒吃货
     * 如果包子 存在      进入等待状态
     */
    @Override
    public void run() {
        String threadName=Thread.currentThread().getName();
        int count=0;
        while (true) {
            synchronized (baoZi) {
                count++;
                if (count > 10) {
                    break;
                }
                if (baoZi.flag) { //如果包子存在
                    try {
                        baoZi.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else { //如果包子不存在
                    System.out.println(threadName+"开始制作"+baoZi.name); //制作包子
                    baoZi.flag=true; //更改包子状态
                    baoZi.notify(); //唤醒同一资源下的其他线程
                }
            }
        }
    }
}
package KeTangTest.XianChengTongXun;
 
public class ThreadTest {
    public static void main(String[] args) {
        //定义资源对象
        BaoZi baoZi=new BaoZi();
        baoZi.name="猪肉香菇";
        baoZi.flag=true;
 
        //定义两个线程,起名字且操作同一个对象
        ChiHuo ch=new ChiHuo("八戒",baoZi);
        ZaoCanDian zcd=new ZaoCanDian("早餐",baoZi);
 
        //自动线程
        zcd.start();
        ch.start();
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值