多线程中的等待与唤醒

一个卖面的面馆,有一个做面的厨师和一个吃面的食客,需要保证,厨师做一碗面,食客吃一碗面,不能一次性多做几碗面,更不能没有面的时候吃面;按照上述操作,进行十轮做面吃面的操作


三组等待与唤醒
在这里插入图片描述

这里是使用第一组
synchronized(锁) wait(线程等待阻塞)notifyAll(唤醒全部线程)

做面方法代码如下 :

    public void makeNoodles() {
        synchronized (this) {
            //如果食客没吃完
            while (number != 0) {
                //等待食客吃完
                try {
                    System.out.println(Thread.currentThread().getName() + "食客没有吃完,弃锁等待中...");
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //食客已经吃完,线程被唤醒,开始做面
            if (number <= 0) {
                number++;
                System.out.println(Thread.currentThread().getName() + "做" + number + "碗面 ----> number=" + number);
            }
            //唤醒食客吃面
            if (number > 0) {
                this.notifyAll();
            }
        }
    }

吃面方法代码如下 :

    public void eatNoodles() {
        synchronized (this) {
            //如果厨师没做好
            while (number <= 0) {
                try {
                    System.out.println(Thread.currentThread().getName() + "没有面条吃,弃锁等待中...");
                    this.wait();//等待厨师做面
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //厨师已经吃好,线程被唤醒,开始吃面
            if (number > 0) {
                System.out.println(Thread.currentThread().getName() + "吃" + number + "碗面 ----> number=" + --number);
            }
            //吃完唤醒厨师做面
            if (number <= 0) {
                this.notifyAll();
            }
        }
    }

多个线程调用做面方法和吃面方法

        CountDownLatch countDownLatch = new CountDownLatch(40);
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                makeNoodles();
                countDownLatch.countDown();
            }
        }, "厨师01").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                eatNoodles();
                countDownLatch.countDown();
            }
        }, "食客01").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                makeNoodles();
                countDownLatch.countDown();
            }
        }, "厨师002").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                eatNoodles();
                countDownLatch.countDown();
            }
        }, "食客002").start();

        countDownLatch.await();

打印执行结果:经常出现厨师(食客)做(吃)完面再次拿到锁又弃锁等待的情况,是因为synchronized 变成了偏向锁,对象的对象头中保存中偏向的线程id


厨师011碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
食客011碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
厨师011碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
食客011碗面 ----> number=0
厨师011碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客011碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
厨师0021碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客011碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
食客002 没有面条吃,弃锁等待中...
厨师011碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客0021碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
食客01 没有面条吃,弃锁等待中...
厨师0021碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客011碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
食客002 没有面条吃,弃锁等待中...
厨师011碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客0021碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
食客01 没有面条吃,弃锁等待中...
厨师0021碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客011碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
食客002 没有面条吃,弃锁等待中...
厨师011碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客0021碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
食客01 没有面条吃,弃锁等待中...
厨师0021碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客011碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
食客002 没有面条吃,弃锁等待中...
厨师011碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客0021碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
食客01 没有面条吃,弃锁等待中...
厨师0021碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客011碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
食客002 没有面条吃,弃锁等待中...
厨师011碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客0021碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
食客01 没有面条吃,弃锁等待中...
厨师0021碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客011碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
食客002 没有面条吃,弃锁等待中...
厨师011碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客0021碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
食客01 没有面条吃,弃锁等待中...
厨师0021碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客011碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
厨师011碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
食客0021碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
厨师0021碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
食客0021碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
厨师0021碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
食客0021碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
厨师0021碗面 ----> number=1
食客0021碗面 ----> number=0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值