终于明白阿里百度为什么拿WaitNotify通知机制考察求职者了

本文主要是介绍终于明白阿里百度为什么拿WaitNotify通知机制考察求职者了,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作为一名java程序员,相信都知道wait/notify的通知机制可以用来实现线程间通信。

求职面试时,不少公司都会出类似这样的题目。笔者有次面试时,面试官就问了这样一个问题:

wait/notify/notifyAll一般适用于什么场景?

由于笔者之前对这个知识点没有重视,面试官调侃说,你对WaitNotify通知机制都没有掌握,难怪你期望薪资那么低。

我们知道,wait表示线程的等待,调用该方法会导致线程阻塞,直至另一线程调用notify或notifyAll方法才可另其继续执行。经典的生产者、消费者模式即是使用wait/notify机制得以完成。

在了解wait/notify通知机制前,我们先回顾下java线程的生命周期。

今天我们针对此知识点,来编写个例子加深理解。

假设我开了一家水果实体店,日常经营主要有两项,一项是进货,一项是卖货。需要满足如下条件:

  1. 往店里进货,前提是店里库存不足,如果库存充足,则无需进货,直到把货卖出去了。

  2. 卖货,前提店里库存充足,库存不足时就要进货。

新建个水果店抽象类AbstractFruitStore

1public interface AbstractFruitStore {
2  void consumer(int num);
3
4  void producer(int num);
5}

水果实体店类实现AbstractFruitStore

 1/**2 * 水果店3 */4public class FruitStore implements AbstractFruitStore {5 private final int MAX_SIZE = 100;6 private LinkedList list = new LinkedList();78 @Override9 public void consumer(int num) {
10    synchronized (list) {
11        //条件不满足,进入等待状态
12        while (num > list.size()) {
13            System.out.println("【要消费】:" + num + "\t【现库存量】:" + list.size() + "\t库存不足,暂不支持消费");
14            try {
15                //条件不满足,生产阻塞
16                list.wait();
17            } catch (InterruptedException e) {
18                e.printStackTrace();
19            }
20        }
21        //条件满足,开始消费
22        for (int i = 0; i < num; i++) {
23            list.remove();
24        }
25        System.out.println("【已消费】:" + num + "\t【现库存量】:" + list.size());
26        list.notifyAll();
27    }
28}
29
30@Override
31public void producer(int num) {
32    synchronized (list) {
33        while (list.size() + num > MAX_SIZE) {
34            System.out.println("【要生产】:" + num + "\t【库存已有】:" + list.size() + "\t库存充足,暂不支持生产");
35            try {
36                //条件不满足,生产阻塞
37                list.wait();
38            } catch (InterruptedException e) {
39                e.printStackTrace();
40            }
41        }
42        for (int i = 0; i < num; i++) {
43            list.add(new Object());
44        }
45        System.out.println("【已生产】:" + num + "\t【现库存量】:" + list.size());
46        list.notifyAll();
47    }
48  }
49}

生产者Producer

 1 /**2  * 生产者3  */4public class Producer extends Thread {5   private int num;6   public AbstractFruitStore abstractFruitStore;78   public Producer(AbstractFruitStore abstractFruitStore) {9    this.abstractFruitStore = abstractFruitStore;
10   }
11
12   public void setNum(int num) {
13    this.num = num;
14   }
15
16   @Override
17   public void run() {
18    producer(num);
19   }
20
21   public void producer(int num) {
22    abstractFruitStore.producer(num);
23  }
24}

消费者Consumer

 1/**2 * 消费者3 */4public class Consumer extends Thread {56    private int num;78    private AbstractFruitStore abstractFruitStore;9
10    public Consumer(AbstractFruitStore abstractFruitStore) {
11    this.abstractFruitStore = abstractFruitStore;
12    }
13
14    public void run() {
15     consumer(num);
16    }
17
18    public void consumer(int num) {
19     abstractFruitStore.consumer(num);
20    }
21
22    public void setNum(int num) {
23     this.num = num;
24   }
25}
 1public class WaitNotifyTest {2 public static void main(String[] args) {3    AbstractFruitStore abstractFruitStore = new FruitStore();4    //消费者对象5    Consumer c1 = new Consumer(abstractFruitStore);6    Consumer c2 = new Consumer(abstractFruitStore);7    Consumer c3 = new Consumer(abstractFruitStore);89    c1.setNum(10);
10    c2.setNum(20);
11    c3.setNum(30);
12
13    // 生产者对象
14    Producer p1 = new Producer(abstractFruitStore);
15    Producer p2 = new Producer(abstractFruitStore);
16    Producer p3 = new Producer(abstractFruitStore);
17    Producer p4 = new Producer(abstractFruitStore);
18
19    p1.setNum(20);
20    p2.setNum(30);
21    p3.setNum(50);
22    p4.setNum(80);
23
24    //启动消费者线程
25    c1.start();
26    c2.start();
27    c3.start();
28    //启动生产者线程
29    p1.start();
30    p2.start();
31    p3.start();
32    p4.start();
33  }
34}

运行结果:

从中我们可以得出,Wait-Notify场景一般和下面3个因素相关:

  1. 状态变量(State Variable)
    当线程需要wait时,是因为一些条件得不到满足导致的。例如往队列里填充数据,当队列元素已经满时,线程就需要wait停止运行。当队列元素有空缺时,再继续自己的执行。

  2. 条件断言(Condition Predicate)


    当线程确定是否进入wait或者是从notify醒来的时候是否继续往下执行,大部分都要测试状态条件是否满足。

  3. 条件队列(Condition Queue)
    每个对象都有一个内置的条件队列,当一个线程在该对象锁上调用wait函数的时候,就会将该线程加入到该对象的条件队列中。

总结

如果线程调用了Object对象的wait()方法,那么线程会处于该对象的等待池中,等待池中的线程不会去竞争该对象的锁。

当有线程调用了Object对象的notify()方法(只随机唤醒一个wait线程)或是notifyAll()方法(唤醒所有wait线程)被唤醒的的线程会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。

优先级高的线程竞争到对象锁的概率大,假若某线程没有竞争到该对象锁,它还会留在锁池中,只有线程再次调用wait()方法,它才会重新回到等待池中。而竞争到对象锁的线程则继续往下执行,直到执行完了synchronized代码块,它会释放掉该对象锁,这时锁池中的线程会继续竞争该对象锁。

一个知识点不仅能考验求职者的对该知识点的掌握程度,还延伸出其他知识点,考验求职者的知识面,难怪阿里百度这样的大公司喜欢在面试时拿它来考验求职者。

由于笔者水平有限,文中纰漏之处在所难免,权当抛砖引玉,不妥之处,请大家批评指正。

 

-END-

作者:洪生鹏  擅长java、Android、qt、小程序平台开发。技术交流、媒体合作、品牌宣传请添加微信: hsp-88ios

猜你喜欢

养成了定期更新简历的习惯,我不再像以前那么焦虑了

更多惊喜,请长按二维码识别关注

你若喜欢,别忘了帮忙点【在看

这篇关于终于明白阿里百度为什么拿WaitNotify通知机制考察求职者了的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/227624

相关文章

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

Maven 配置中的 <mirror>绕过 HTTP 阻断机制的方法

《Maven配置中的<mirror>绕过HTTP阻断机制的方法》:本文主要介绍Maven配置中的<mirror>绕过HTTP阻断机制的方法,本文给大家分享问题原因及解决方案,感兴趣的朋友一... 目录一、问题场景:升级 Maven 后构建失败二、解决方案:通过 <mirror> 配置覆盖默认行为1. 配置示

Redis过期删除机制与内存淘汰策略的解析指南

《Redis过期删除机制与内存淘汰策略的解析指南》在使用Redis构建缓存系统时,很多开发者只设置了EXPIRE但却忽略了背后Redis的过期删除机制与内存淘汰策略,下面小编就来和大家详细介绍一下... 目录1、简述2、Redis http://www.chinasem.cn的过期删除策略(Key Expir

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中

Jvm sandbox mock机制的实践过程

《Jvmsandboxmock机制的实践过程》:本文主要介绍Jvmsandboxmock机制的实践过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、背景二、定义一个损坏的钟1、 Springboot工程中创建一个Clock类2、 添加一个Controller

如何关闭Mac的Safari通知? 3招教你关闭Safari浏览器网站通知的技巧

《如何关闭Mac的Safari通知?3招教你关闭Safari浏览器网站通知的技巧》当我们在使用Mac电脑专注做一件事情的时候,总是会被一些消息推送通知所打扰,这时候,我们就希望关闭这些烦人的Mac通... Safari 浏览器的「通知」功能本意是为了方便用户及时获取最新资讯,但很容易被一些网站滥用,导致我们

Dubbo之SPI机制的实现原理和优势分析

《Dubbo之SPI机制的实现原理和优势分析》:本文主要介绍Dubbo之SPI机制的实现原理和优势,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Dubbo中SPI机制的实现原理和优势JDK 中的 SPI 机制解析Dubbo 中的 SPI 机制解析总结Dubbo中

Java 的 Condition 接口与等待通知机制详解

《Java的Condition接口与等待通知机制详解》在Java并发编程里,实现线程间的协作与同步是极为关键的任务,本文将深入探究Condition接口及其背后的等待通知机制,感兴趣的朋友一起看... 目录一、引言二、Condition 接口概述2.1 基本概念2.2 与 Object 类等待通知方法的区别

嵌入式Linux驱动中的异步通知机制详解

《嵌入式Linux驱动中的异步通知机制详解》:本文主要介绍嵌入式Linux驱动中的异步通知机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、异步通知的核心概念1. 什么是异步通知2. 异步通知的关键组件二、异步通知的实现原理三、代码示例分析1. 设备结构

JVM垃圾回收机制之GC解读

《JVM垃圾回收机制之GC解读》:本文主要介绍JVM垃圾回收机制之GC,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、死亡对象的判断算法1.1 引用计数算法1.2 可达性分析算法二、垃圾回收算法2.1 标记-清除算法2.2 复制算法2.3 标记-整理算法2.4