面试流程看明白啥是线程等待通知机制

先看定义

  • notify 通知一个在对象上等待的线程,使其从wait()方法返回,而返回的前提是该线程获取到了对象的锁
  • notifyAll 通知所有在该对象上的线程
  • wait 调用该方法线程进入WAITING的状态,只有等待另外线程的通知或被中断才会返回,需要注意,调用wait()后,会释放对象的锁

看一段示例代码

场景是这样的wait同学跟notify同学一起去面试,他俩在一个同步队列里面,wait先到的先进行了面试,结果就面了30min,面试官让他在旁边的办公室等通知;hr请他到隔壁房间去,让notify同学进来了,跟面试官相见恨晚,聊了足足1.5h,hr已经发出了通知马上出结果,然而notify同学似乎还不满足,撩起了hr小姐姐...

public class WaitNotify {
/**
 * flag表示是否通过面试 默认值认为人人皆可通过
 */
static boolean flag = true;
/**
 * hrLock表示hr
 */
static Object hrLock = new Object();

public static void main(String[] args) throws Exception {
    Thread waitThread = new Thread(new Wait(), "WaitThread");
    waitThread.start();
    // 模拟间隔2分钟,notify面试同学进场
    // TODO TimeUnit.SECONDS.sleep(60*2);
    Thread notifyThread = new Thread(new Notify(), "NotifyThread");
    notifyThread.start();
}

static class Wait implements Runnable {
    @Override
    public void run() {
        // 加锁,拥有hrLock的Monitor - hr带着wait同学去见面试官
        synchronized (hrLock) {
            // wait同学进行面试
            while (flag) {
                try {
                    // TODO 面试进行了30min
                    System.out.println(Thread.currentThread().getName() + "同学你在旁边办公室等通知 hrLock.wait -> " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
                    // 释放锁 - hr开始清场,让wait同学到旁边去
                    hrLock.wait();
                } catch (InterruptedException e) {
                }
            }
            // 面试不通过
            System.out.println(Thread.currentThread().getName() + "面试不通过 -> " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
        }
    }
}

static class Notify implements Runnable {
    @Override
    public void run() {
        // 加锁,拥有hrLock的Monitor - hr带着notify同学去见面试官
        synchronized (hrLock) {
            // TODO notify跟面试官聊得很愉快,聊了1.5h
            // 获取lock的锁,然后进行通知,通知时不会释放lock的锁,
            // 直到当前线程释放了lock后,WaitThread才能从wait方法中返回
            System.out.println(Thread.currentThread().getName() + "同学,你技术面通过了 hrLock.notifyAll -> " + new SimpleDateFormat("HH:mm:ss").format(new Date()));

            // hr通知所有处于等通知状态的同学、我马上过来给你们结果(PS:hr心里早已打算让wait同学gg)
            hrLock.notifyAll();
            flag = false;

            // TODO 模拟间隔5分钟
        }
        // 再次加锁 - notify同学差不多通过了,拉起hr小姐姐聊起了人生
        synchronized (hrLock) {
            System.out.println(Thread.currentThread().getName() + "同学你面试通过了,咱俩后面有空再唠(emmmmm.) -> " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
        }
    }
}
}
复制代码

结果如下

WaitThread同学你在旁边办公室等通知 hrLock.wait -> 18:37:14
NotifyThread同学,你技术面通过了 hrLock.notifyAll -> 18:37:14
NotifyThread同学你面试通过了,咱俩后面有空再唠(emmmmm.) -> 18:37:14
WaitThread面试不通过 -> 18:37:14
复制代码

来张彩图了解一下流程

解释如下

  • 1.WaitThread首先获取了对象的锁,然后调用对象的wait()方法,从而放弃了锁并进入了对象的等待队列WaitQueue中,进入等待状态。
  • 2.由于WaitThread释放了对象的锁,NotifyThread随后获取了对象的锁,并调用对象的notify()方法,将WaitThread从WaitQueue移到SynchronizedQueue中,此时WaitThread的状态变为阻塞状态。
  • 3.NotifyThread释放了锁之后,WaitThread再次获取到锁并从wait()方法返回继续执行。

等待/通知的经典范式

等待方规则

  • 1)获取对象的锁
  • 2)如果条件不满足,那么调用对象的wait()方法,被通知后仍要检查条件
  • 3)条件满足则执行对应的逻辑 伪代码
synchronized(对象) {
       while(条件不满足) {
              对象.wait();
       }
       对应的处理逻辑
}
复制代码

通知方规则

  • 1)获得对象的锁。

  • 2)改变条件。

  • 3)通知所有等待在对象上的线程。 伪代码

synchronized(对象) {
       改变条件
       对象.notifyAll();
}
复制代码

参考资料《Java并发编程的艺术》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值