发布时间:2024-03-03 10:39:11
今天有一个校招师弟分享了他腾讯一面关于单例模式的面试,很有意思,特地分享给大家。 // 「面试官」: 嗨,我看你简历上对设计模式很熟悉啊。能聊聊单例模式吗?就跟我解释给个五岁小孩听似的。 「应聘者」: 哈哈,好的,那我就通俗点说。单例模式,就像我们班里只能有一个班长一样。无论发生什么,班长都是那个人,大家都知道找他就行了。 「面试官」: 听起来很实用。那你能给我举个实际开发中用到单例模式的例子吗? 「应聘者」: 当然。比如说,我们的应用要连接打印机。我们不可能让它每次打印都去连接一次打印机,那样太慢了。所以我们用单例模式创建一个打印管理器,它始终保持连接状态。这就像是我们随时都能打印,因为打印管理器始终在线。 「面试官」: 了解了。那实现单例模式有什么技巧? 「应聘者」: 实现它,关键得让这个类不能随便被创建多个实例。我们可以让构造函数私有,这就像是说'这个类的创建权我自己说了算'。然后提供一个公共的方法,比如叫 「面试官」: 有没有考虑过多线程的情况呢? 「应聘者」: 哦,肯定的。在多线程下,可能会有多个线程同时尝试创建实例,这时候就需要用到锁来确保只创建一个实例。这就像是大家排队进电影院,虽然大家都想第一个进去,但门口的工作人员确保一次只让一个人进。 「面试官」: 听起来不错。那能展示一下具体代码吗? 「应聘者」: 当然,这里有一个懒汉模式的单例实现:
「面试官」: 这个双重检查锁定是怎么一回事?能解释一下吗? 「应聘者」: 当然。这个机制是为了防止在多线程环境下创建多个实例。第一次检查是为了避免不必要的同步,也就是说,如果实例已经被创建,就不需要同步操作了。但如果还没有被创建,就需要进行同步,这就是第二次检查,确保在当前线程进入同步块之前,没有其他线程已经创建了实例。 「面试官」: 明白了。但我听说还有饿汉式的单例,那又是怎样的? 「应聘者」: 对,饿汉式和懒汉式不同的地方在于,它会在类加载的时候就立刻初始化实例,这样就不用担心多线程问题了。可以这样写:
「面试官」: 听起来好像饿汉式比懒汉式更简单、更安全啊。 「应聘者」: 确实,在某些情况下是这样的。但饿汉式也有它的缺点,比如它在类加载时就创建了实例,即使我们可能根本就用不到这个实例,也会占用内存资源。所以选择哪种方式,还得看具体的场景和需求。 「面试官」: 有没有哪种方法是最好的实践呢? 「应聘者」: 在Java中,我觉得最好的做法是用枚举来实现单例。它不仅能避免多线程同步的问题,还能抵抗反射攻击和避免序列化的问题。这样写:
「面试官」: 哇,这个我还真不知道,学到了。感谢你的分享。那你有没有遇到过什么特别需要单例模式的情况?有没有哪次特别难忘? 「应聘者」: 有的。我曾在一个大型的应用程序中工作,那里有一个配置管理器,控制着所有的系统配置。我们使用了单例模式,确保整个应用中数据的一致性,并且避免了不必要的资源浪费。那次经历让我深刻体会到了单例模式的强大之处,也让我对设计模式有了更深的理解。 「面试官」: 真不错,这确实是单例模式的一个经典用例。谢谢你今天的分享,你回答得很棒。我们很快会和你联系的。 「应聘者」: 谢谢您!期待能有机会和贵公司合作。 ![]() 点击关注我们 |