wait_notify-并发编程(Java)

1、wait/notify 原理

在这里插入图片描述

  • owner线程发现条件不满足,调用wait方法,即可进入WaitSet变为WATING状态。
  • BLOCKED和WATING状态的线程都处于阻塞状态,不占用CPU时间片。
  • BLOCKED状态线程,会在Owner线程释放锁时唤醒。
  • WATING状态的线程会在Owner线程调用notify或者notifyAll时唤醒,但唤醒后并不会立即获取锁,会进入EntryList竞争锁资源。

2、API

  • obj.wati():让进入object监视器的线程到WaitSet等待
  • obj.wait(long timeout):让进入object监视器的线程到WaitSet等待,最多等待timeout 毫秒
  • obj.notify():随机唤醒一个在object 上WaitSet中的等待的线程
  • obj.notifyAll():唤醒全部在object 上WaitSet中的等待的线程
@Slf4j(topic = "w.WaitNotifyTest01")
public class WaitNotifyTest01 {
    final static Object obj = new Object();

    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            synchronized (obj) {
                log.debug("执行代码...");
                try {
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                log.debug("{} 线程其他代码...", Thread.currentThread().getName());
            }
        }, "t1").start();

        new Thread(() -> {
            synchronized (obj) {
                log.debug("执行代码...");
                try {
                    // 等待条件
                    obj.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                log.debug("{} 线程其他代码...", Thread.currentThread().getName());
            }
        }, "t2").start();

        TimeUnit.SECONDS.sleep(1);

        new Thread(() -> {
            synchronized (obj) {
//                log.debug("条件满足,通知可以继续执行...");
//                obj.notify();

                log.debug("条件都满足,通知全部继续执行...");
                obj.notifyAll();
            }
        }, "t3").start();
    }
}

带参wait示例代码在后面。

3、wait(long n) 和 sleep(long n)区别

  1. wait是Object对象的方法,sleep是Thread类的静态方法
  2. wait需要和synchronized一起使用,sleep不需要。
  3. 对象调用wait,当前线程会释放锁对象;而sleep在睡眠的时候,不会释放锁对象。

4、唤醒不同条件下等待的多线程

简单场景描述:博主租住的小区现在正在改造,卡车司机王师傅在运送建筑垃圾,此时卡车没油了,需要等待其他人吧柴油送来继续干活;负责线路改造的李师傅,需要操作电转在墙壁上钻孔,但是电还没有接通,需要等待其他人把电接通。如果送油的先来了就通知王师傅,可以继续运行建筑垃圾了,如果电先接通了就通知李师傅继续钻孔。

代码如下:

@Slf4j(topic = "w.PostureStep01")
public class PostureStep03 {
    static final Object room = new Object();
    // 是否又电
    static boolean hasElectric = false;
    // 是否有柴油
    static boolean hasDiesel = false;

    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            synchronized (room) {
                log.debug("电有了没?[{}]", hasElectric);

                while (!hasElectric) {
                    log.debug("没电,先歇会!");
                    try {
                        room.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                log.debug("电接通了?[{}]", hasElectric);
                if (hasElectric) {
                    log.debug("开始干活!");
                }

            }
        },"李师傅").start();

        new Thread(() -> {
            synchronized (room) {
                log.debug("柴油送到没?[{}]", hasElectric);
                while (!hasDiesel) {
                    log.debug("柴油没送到,先歇会!");
                    try {
                        room.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                log.debug("柴油送到没?[{}]", hasElectric);
                if (hasDiesel) {
                    log.debug("开始干活!");
                }

            }
        },"王师傅").start();

        TimeUnit.SECONDS.sleep(1);

        new Thread(() -> {
            synchronized (room) {
                hasElectric = true;
                log.debug("电接通了!");
                room.notifyAll();
            }
        }, "工人").start();
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

gaog2zh

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

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

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

打赏作者

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

抵扣说明:

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

余额充值