春招启动!吐血分享!腾讯一面实录: 请5min实现单例模式!

简介: 春招启动!吐血分享!腾讯一面实录: 请5min实现单例模式!

「面试官」: 嗨,我看你简历上对设计模式很熟悉啊。能聊聊单例模式吗?就跟我解释给个五岁小孩听似的。

「应聘者」: 哈哈,好的,那我就通俗点说。单例模式,就像我们班里只能有一个班长一样。无论发生什么,班长都是那个人,大家都知道找他就行了。

「面试官」: 听起来很实用。那你能给我举个实际开发中用到单例模式的例子吗?

「应聘者」: 当然。比如说,我们的应用要连接打印机。我们不可能让它每次打印都去连接一次打印机,那样太慢了。所以我们用单例模式创建一个打印管理器,它始终保持连接状态。这就像是我们随时都能打印,因为打印管理器始终在线。

「面试官」: 了解了。那实现单例模式有什么技巧?

「应聘者」: 实现它,关键得让这个类不能随便被创建多个实例。我们可以让构造函数私有,这就像是说'这个类的创建权我自己说了算'。然后提供一个公共的方法,比如叫getInstance,让大家通过这个方法来获取这个唯一的实例。

「面试官」: 有没有考虑过多线程的情况呢?

「应聘者」: 哦,肯定的。在多线程下,可能会有多个线程同时尝试创建实例,这时候就需要用到锁来确保只创建一个实例。这就像是大家排队进电影院,虽然大家都想第一个进去,但门口的工作人员确保一次只让一个人进。

「面试官」: 听起来不错。那能展示一下具体代码吗?

「应聘者」: 当然,这里有一个懒汉模式的单例实现:

public class Singleton {
    private static Singleton instance;
    private Singleton (){}

    public static Singleton getInstance() {
        if (instance == null) {  
            synchronized (Singleton.class) {  
                if (instance == null) {  
                    instance = new Singleton();  
                }
            }
        }
        return instance;
    }
}

「面试官」: 这个双重检查锁定是怎么一回事?能解释一下吗?

「应聘者」: 当然。这个机制是为了防止在多线程环境下创建多个实例。第一次检查是为了避免不必要的同步,也就是说,如果实例已经被创建,就不需要同步操作了。但如果还没有被创建,就需要进行同步,这就是第二次检查,确保在当前线程进入同步块之前,没有其他线程已经创建了实例。

「面试官」: 明白了。但我听说还有饿汉式的单例,那又是怎样的?

「应聘者」: 对,饿汉式和懒汉式不同的地方在于,它会在类加载的时候就立刻初始化实例,这样就不用担心多线程问题了。可以这样写:

public class SingleObject {

   private static SingleObject instance = new SingleObject();

   private SingleObject(){}

   public static SingleObject getInstance(){
      return instance;
   }
}

「面试官」: 听起来好像饿汉式比懒汉式更简单、更安全啊。

「应聘者」: 确实,在某些情况下是这样的。但饿汉式也有它的缺点,比如它在类加载时就创建了实例,即使我们可能根本就用不到这个实例,也会占用内存资源。所以选择哪种方式,还得看具体的场景和需求。

面试官」: 有没有哪种方法是最好的实践呢?

「应聘者」: 在Java中,我觉得最好的做法是用枚举来实现单例。它不仅能避免多线程同步的问题,还能抵抗反射攻击和避免序列化的问题。这样写:

public enum EasySingleton {
    INSTANCE;
    public void show(){
        System.out.println("Hello, Singleton!");
    }
}

「面试官」: 哇,这个我还真不知道,学到了。感谢你的分享。那你有没有遇到过什么特别需要单例模式的情况?有没有哪次特别难忘?

「应聘者」: 有的。我曾在一个大型的应用程序中工作,那里有一个配置管理器,控制着所有的系统配置。我们使用了单例模式,确保整个应用中数据的一致性,并且避免了不必要的资源浪费。那次经历让我深刻体会到了单例模式的强大之处,也让我对设计模式有了更深的理解。

「面试官」: 真不错,这确实是单例模式的一个经典用例。谢谢你今天的分享,你回答得很棒。我们很快会和你联系的。

「应聘者」: 谢谢您!期待能有机会和贵公司合作。







相关文章
|
11月前
|
网络协议 安全 网络安全
HCIP-Datacom H12-821 题库 (15)
HCIP-Datacom H12-821 题库 (15)
187 1
HCIP-Datacom H12-821 题库 (15)
|
5月前
|
机器人 数据安全/隐私保护
AppFlow:钉钉机器人使用Qwen3自动回复
近期,Qwen3正式发布并开源了8款「混合推理模型」,包括两款MoE模型和六个Dense模型。这些模型已在AppFlow上全面开放调用,支持钉钉、微信等多种渠道使用。本文将详细介绍如何将Qwen3集成到钉钉机器人中,涵盖创建钉钉应用、配置消息卡片、生成连接流以及发布应用版本等步骤,帮助用户快速实现与Qwen3的交互功能。通过简单的配置,您即可在钉钉群聊中与Qwen3进行交流互动。
253 8
AppFlow:钉钉机器人使用Qwen3自动回复
|
算法 C++
【基础算法】顺序查找 折半查找 & C++实现
顺序查找比较简单,就是顺序遍历我们所要查找的内容,判断并找出相应的目标数。比较简单,在这里不用图形说明程序实现具体情况。当面临大量数据时,顺序查找的效率非常低,时间复杂度大,所以会采用其他方法进行查找。
318 0
【基础算法】顺序查找 折半查找 & C++实现
|
数据安全/隐私保护
matlab 地震波基线校正,kik地震基线漂移,校正加速度,批量处理
地震波格式转换、时程转换、峰值调整、规范反应谱、计算反应谱、计算持时、生成人工波、时频域转换、数据滤波、基线校正、Arias截波、傅里叶变换、耐震时程曲线、脉冲波合成与提取、三联反应谱、地震动参数、延性反应谱、地震波缩尺、功率谱密度
|
缓存 应用服务中间件 API
Nginx七层(应用层)反向代理:HTTP反向代理proxy_pass篇(三)
Nginx七层(应用层)反向代理:HTTP反向代理proxy_pass篇(三)
208 3
|
JavaScript 前端开发
react18【系列实用教程】双向绑定表单 (2024最新版)含受控组件、非受控组件、单行多行输入框 input,下拉选择 select,单选 radio,多选 checkbox,标签 label
react18【系列实用教程】双向绑定表单 (2024最新版)含受控组件、非受控组件、单行多行输入框 input,下拉选择 select,单选 radio,多选 checkbox,标签 label
294 1
|
机器学习/深度学习 Linux PyTorch
Dataset and DataLoader 加载数据集
Dataset and DataLoader 加载数据集
278 0
|
存储 定位技术 芯片
为何手机gps定位需要流量,而车载不需要?
为何手机gps定位需要流量,而车载不需要?
438 0
为何手机gps定位需要流量,而车载不需要?
|
消息中间件 存储 数据处理
实时计算 Flink版产品使用合集之有没有rocketMq的connector
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
341 1
|
存储 搜索推荐 程序员
数据结构项目实战——通讯录
C语言通讯录是一个使用C语言编写的简单程序,用于存储和管理联系人信息。该程序允许用户添加、删除、查找和显示通讯录中的联系人。每个联系人通常包括姓名、电话号码和电子邮件地址等基本信息。程序使用结构体来存储联系人信息,并使用数组或链表等数据结构来组织和管理通讯录。通过命令行界面与用户进行交互,用户可以通过输入命令来执行相应的操作。C语言通讯录程序可以用于个人或小型组织的信息管理,提高联系人信息的管理效率。
236 0