终于明白阿里百度为什么拿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

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

百度/小米/滴滴/京东,中台架构比较

小米中台建设实践 01 小米的三大中台建设:业务+数据+技术 业务中台--从业务说起 在中台建设中,需要规范化的服务接口、一致整合化的数据、容器化的技术组件以及弹性的基础设施。并结合业务情况,判定是否真的需要中台。 小米参考了业界优秀的案例包括移动中台、数据中台、业务中台、技术中台等,再结合其业务发展历程及业务现状,整理了中台架构的核心方法论,一是企业如何共享服务,二是如何为业务提供便利。

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

【Tools】大模型中的自注意力机制

摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样                      🎵 方芳《摇太阳》 自注意力机制(Self-Attention)是一种在Transformer等大模型中经常使用的注意力机制。该机制通过对输入序列中的每个元素计算与其他元素之间的相似性,

如何通俗理解注意力机制?

1、注意力机制(Attention Mechanism)是机器学习和深度学习中一种模拟人类注意力的方法,用于提高模型在处理大量信息时的效率和效果。通俗地理解,它就像是在一堆信息中找到最重要的部分,把注意力集中在这些关键点上,从而更好地完成任务。以下是几个简单的比喻来帮助理解注意力机制: 2、寻找重点:想象一下,你在阅读一篇文章的时候,有些段落特别重要,你会特别注意这些段落,反复阅读,而对其他部分

【Tools】大模型中的注意力机制

摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样                      🎵 方芳《摇太阳》 在大模型中,注意力机制是一种重要的技术,它被广泛应用于自然语言处理领域,特别是在机器翻译和语言模型中。 注意力机制的基本思想是通过计算输入序列中各个位置的权重,以确

FreeRTOS内部机制学习03(事件组内部机制)

文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

UVM:callback机制的意义和用法

1. 作用         Callback机制在UVM验证平台,最大用处就是为了提高验证平台的可重用性。在不创建复杂的OOP层次结构前提下,针对组件中的某些行为,在其之前后之后,内置一些函数,增加或者修改UVM组件的操作,增加新的功能,从而实现一个环境多个用例。此外还可以通过Callback机制构建异常的测试用例。 2. 使用步骤         (1)在UVM组件中内嵌callback函