java多线程等待唤醒机制详细介绍

java多线程等待唤醒机制

一. 方法介绍

方法说明
void wait()线程等待,等待的过程中线程会释放锁,需要被其他线程调用notify方法将其唤醒,重新抢锁执行
void notify()线程唤醒,一次唤醒一个等待线程;如果有多条线程等待,则随机唤醒一条等待线程
void notifyAll()唤醒所有等待线程

二.等待唤醒案例分析(线程之间的通信)

要求:一个线程生产,一个线程消费,不能连续生产,不能连续消费 -> 等待唤醒机制(生产者,消费者)(线程之间的通信)

这里一包子铺与消费者之间关系举列

1. 生产者(包子铺)

包子铺负责生产包子

那么如何表示包子铺 --> 我们这里可以定义一个count变量 , 代表生产包子的数目 , 每次生产count++

2. 消费者

消费者负责消费包子 , 每次消费的过程中只需要打印消费了第多少个包子即可

3. 生产者与消费者的关系

问1. 那么我们如何来表示现在是否存在包子 , 是需要生产还是消费?

这里只需要再定义一个标识符flag , 用于判断即可 , 当flag为true则有包子调用生产者 , 反之调用消费者

问2. 我们该如何保证在生产到一半的时候 , cpu自动切换到消费?

很简单使用线程锁即可

问3. 如何保证生产一个 , 消费一个?

即使加锁我们也无法保证生产和消费同步

这里我们就需要使用到等待和唤醒方法了

三. 代码阐述

  1. 创建包子铺类

    在该类中我们需要对getCount和setCount进行修改 , 使其对应成为消费和生产方法

    /*
       count和flag可以定义成包装类
       但是要记得给count和flag手动赋值
       不然对于本案例来说,容易出现空指针异常
     */
    public class BaoZiPu {
        //代表包子的count
        private int count;
        //代表是否有包子的flag
        private boolean flag;
    
        public BaoZiPu() {
        }
    
        public BaoZiPu(int count, boolean flag) {
            this.count = count;
            this.flag = flag;
        }
    
        /*
           getCount 改造成消费包子方法
           直接输出count
         */
        public void getCount() {
            System.out.println("消费了..............第"+count+"个包子");
        }
    
        /*
           setCount 改造成生产包子
           count++
         */
        public void setCount() {
            count++;
            System.out.println("生产了...第"+count+"个包子");
        }
    
        public boolean isFlag() {
            return flag;
        }
    
        public void setFlag(boolean flag) {
            this.flag = flag;
        }
    }
    
    
  2. 定义生产者类

    生产线程 , 在循环中通过判断flag来决定是否生产 . 如果flag为true则已有包子不需要生产 , 设置该线程等待即可 , 反之没有包子则生产 , count+1 , 将flag改为false , 并唤醒消费线程

    public class Product implements Runnable{
        private BaoZiPu baoZiPu;
    
        public Product(BaoZiPu baoZiPu) {
            this.baoZiPu = baoZiPu;
        }
    
        @Override
        public void run() {
            while(true){
    
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
    
                synchronized (baoZiPu){
                    //1.判断flag是否为true,如果是true,证明有包子,生产线程等待
                    if (baoZiPu.isFlag()==true){
                        try {
                            baoZiPu.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
    
                    //2.如果flag为false,证明没有包子,开始生产
                    baoZiPu.setCount();
                    //3.改变flag状态,为true,证明生产完了,有包子了
                    baoZiPu.setFlag(true);
                    //4.唤醒消费线程
                    baoZiPu.notify();
                }
            }
        }
    }
    
    
  3. 消费者类

    逻辑和生产者类似就不过多赘述

    public class Consumer implements Runnable{
        private BaoZiPu baoZiPu;
    
        public Consumer(BaoZiPu baoZiPu) {
            this.baoZiPu = baoZiPu;
        }
    
        @Override
        public void run() {
            while(true){
    
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
    
                synchronized (baoZiPu){
                    //1.判断flag是否为false,如果是false,证明没有包子,消费线程等待
                    if (baoZiPu.isFlag()==false){
                        try {
                            baoZiPu.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
    
                    //2.如果flag为true,证明有包子,开始消费
                    baoZiPu.getCount();
                    //3.改变flag状态,为false,证明消费完了,没 有包子了
                    baoZiPu.setFlag(false);
                    //4.唤醒生产线程
                    baoZiPu.notify();
                }
            }
        }
    }
    
    
  4. 实现类

    public class Test01 {
        public static void main(String[] args) {
            BaoZiPu baoZiPu = new BaoZiPu();
    
            Product product = new Product(baoZiPu);
            Consumer consumer = new Consumer(baoZiPu);
    
            Thread t1 = new Thread(product);
            Thread t2 = new Thread(consumer);
    
            t1.start();
            t2.start();
        }
    }
    
  • 29
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

攒了一袋星辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值