行业资讯 2025年08月6日
0 收藏 0 点赞 236 浏览 1995 个字
摘要 :

文章目录 wait-ify 基本使用 代码优化 wait-ify 基本使用 需要获取对象锁后才可以调用 锁对象.wait(),notify 随机唤醒一个线程,notifyAll 唤醒所有线程去竞争 CPU O……




  • wait-ify
    • 基本使用
    • 代码优化

    wait-ify

    基本使用

    需要获取对象锁后才可以调用 锁对象.wait()notify 随机唤醒一个线程,notifyAll 唤醒所有线程去竞争 CPU
    Object 类 API:

    public final void notify():唤醒正在等待对象监视器的单个线程。
    public final void notifyAll():唤醒正在等待对象监视器的所有线程。
    public final void wait():导致当前线程等待,直到另一个线程调用该对象的 notify() 方法或 notifyAll()方法。
    public final native void wait(long timeout):有时限的等待, 到n毫秒后结束等待,或是被唤醒
    

    说明:wait 是挂起线程,需要唤醒的都是挂起操作,阻塞线程可以自己去争抢锁,挂起的线程需要唤醒后去争抢锁
    对比 sleep():

    • 原理不同:sleep() 方法是属于 Thread 类,是线程用来控制自身流程的,使此线程暂停执行一段时间而把执行机会让给其他线程;wait() 方法属于 Object 类,用于线程间通信
    • 锁的处理机制不同:调用 sleep() 方法的过程中,线程不会释放对象锁,当调用 wait() 方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池(不释放锁其他线程怎么抢占到锁执行唤醒操作),但是都会释放 CPU
    • 使用区域不同:wait() 方法必须放在**同步控制方法和同步代码块(先获取锁)**中使用,sleep() 方法则可以放在任何地方使用

    底层原理:

    • Owner 线程发现条件不满足,调用 wait 方法,即可进入 WaitSet 变为 WAITING 状态
    • BLOCKED 和 WAITING 的线程都处于阻塞状态,不占用 CPU 时间片
    • BLOCKED 线程会在 Owner 线程释放锁时唤醒
    • WAITING 线程会在 Owner 线程调用 notify 或 notifyAll 时唤醒,唤醒后并不意味者立刻获得锁,需要进入 EntryList 重新竞争


    代码优化

    虚假唤醒:notify 只能随机唤醒一个 WaitSet 中的线程,这时如果有其它线程也在等待,那么就可能唤醒不了正确的线程
    解决方法:采用 notifyAll
    notifyAll 仅解决某个线程的唤醒问题,使用 if + wait 判断仅有一次机会,一旦条件不成立,无法重新判断
    解决方法:用 while + wait,当条件不成立,再次 wait

    @Slf4j(topic = "c.demo")
    public class demo {
        static final Object room = new Object();
        static boolean hasCigarette = false;    //有没有烟
        static boolean hasTakeout = false;
    
        public static void main(String[] args) throws InterruptedException {
            new Thread(() -> {
                synchronized (room) {
                    log.debug("有烟没?[{}]", hasCigarette);
                    while (!hasCigarette) {//while防止虚假唤醒
                        log.debug("没烟,先歇会!");
                        try {
                            room.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    log.debug("有烟没?[{}]", hasCigarette);
                    if (hasCigarette) {
                        log.debug("可以开始干活了");
                    } else {
                        log.debug("没干成活...");
                    }
                }
            }, "小南").start();
    
            new Thread(() -> {
                synchronized (room) {
                    Thread thread = Thread.currentThread();
                    log.debug("外卖送到没?[{}]", hasTakeout);
                    if (!hasTakeout) {
                        log.debug("没外卖,先歇会!");
                        try {
                            room.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    log.debug("外卖送到没?[{}]", hasTakeout);
                    if (hasTakeout) {
                        log.debug("可以开始干活了");
                    } else {
                        log.debug("没干成活...");
                    }
                }
            }, "小女").start();
    
    
            Thread.sleep(1000);
            new Thread(() -> {
            // 这里能不能加 synchronized (room)?
                synchronized (room) {
                    hasTakeout = true;
                    //log.debug("烟到了噢!");
                    log.debug("外卖到了噢!");
                    room.notifyAll();
                }
            }, "送外卖的").start();
        }
    }
    

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/10375.html

管理员

相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

988
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

465
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

348
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

456
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

517
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

832
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号