`
kissuyoyo
  • 浏览: 15137 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

如何写出让面试官满意的java单例

    博客分类:
  • java
 
阅读更多

java中单例模式是一种常见的设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。

  今天暂且不谈单例模式的用途,说一说如果在面试的时候面试官让你敲一段代码实现单例模式的情况下如何写出让面试官眼前一亮的单例代码。而接下来的实例将用Java语言编写。

想要了解更多Java知识点击加入我们一起学习交流一起进步吧!

 

  说到单例模式,第一个想到的是该类中有一个初始化为null的自身引用,且被private修饰符修饰,其它类不能直接访问。除此之外,单例模式的类还需要有private的构造方法,这一点不难理解,如果构造方法是public的,那么类外部可以直接调用该类的构造方法,如此一来便不具备单例的特性。那么如何获取该类唯一的实例呢?这便需要一个公有的获取器,该方法返回值类型是单例模式类,返回的结果自然是该类中唯一的实例。现在思路有了,我们就可以实现最简单的单例模式类:

  不得不说,这样的做法确实达到了单例模式的要求,正常情况下系统中只有一个Singleton的对象。但是如果存在并发的情况呢?两个用户同时访问该类的获取器,此时假设Singleton对象还未被实例化,那么系统将会两次调用构造方法,这样一来系统中就会存在两个Singleton类的实例。说明这种方式的单例没有考虑到并发情况,说明面试者只是粗略的了解单例模式,并没有加以深入思考,想让面试官满意?呵呵呵

  Java相较于C++而言,个人观点编程的难易度上来说要容易很多。在考虑线程同步时一个synchronized关键字便能解决普通加锁问题。synchronized关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。也就是说当两个线程同时访问类中synchronized方法或代码块时,只能有一个线程执行其代码,另一个只能等待当前线程调用结束后才能访问。这下子单例的实现就so easy了!只要对代码稍加改动即可:

  这样的写法面试官会觉得你这个面试者在思考问题的时候比较全面,考虑到并发的情况,相较之前的方式面试官会觉得:少年,我看好你哦!

  然而光是让面试官看好是不够的,我们要让他欣赏,通过单例这样的小问题便能拿到offer。也就是说第二种实现方式是可以进行优化的。那么如何优化?我们看到,当前系统中每次调用获取方法时便会进行加锁,而加锁需要的时间便是我们可以进行优化的地方。现在我所想的是我们只需要在第一次调用时加一次锁往后便再也不需要加锁了,这样一来就省下了每次调用加锁的时间,虽然计算机执行加锁的时间很短但久而久之也是相当长的一段时间。

  那么如何实现呢?这需要引入另一个关键字volatile。volatile修饰的话就可以确保instance = new Singleton();对应的指令不会重排序(JVM当发现代码执行顺序变化但结果不变时可能会改变执行顺序来提升自身性能。坑爹啊。。。),也是线程安全的。

  如何理解?

  线程 1 进入get 方法。

  由于single 为null,线程 1 在 //1 处进入 synchronized块。

  线程 1 被线程 2 预占。

  线程 2 进入get 方法。

  由于single 仍旧为null,线程 2 试图获取 //1 处的锁。然而,由于线程 1 持有该锁,线程 2 在 //1 处阻塞。

  线程 2 被线程 1 预占。

  线程 1 执行,由于在 //2 处实例仍旧为null,线程 1 还创建一个Singleton对象并将其引用赋值给single。

  线程 1 退出 synchronized块并从 get方法返回实例。

  线程 1 被线程 2 预占。

  线程 2 获取 //1 处的锁并检查single 是否为null。

  由于single 是非 null的,并没有创建第二个Singleton对象,由线程 1 创建的对象被返回。

  像这样的程序,面试官看完还能不给你offer吗?奔跑吧少年,java路上前途不可估量啊!

分享到:
评论

相关推荐

    Java面试特别包

    面试实录,如果存在,将提供真实面试的场景和对话,让读者有机会了解面试官的提问方式和期望的回答形式,从而更好地模拟真实的面试环境,提高应试技巧。 在准备Java面试时,以下知识点尤其重要: 1. **Java基础**...

    JAVA面试大全

    在Java面试中,面试官通常会考察求职者对于基础知识、数据结构与算法、多线程、集合框架、网络编程、异常处理、JVM原理、设计模式以及最新的技术趋势等方面的知识。下面我们将深入探讨这些关键知识点。 1. **基础...

    Java面试题总结

    面试官可能会让你现场编写或解释算法的实现。 3. **多线程**:Java提供了丰富的多线程支持,如Thread类、Runnable接口、ExecutorService、Synchronized关键字、volatile、Lock接口等。面试时可能会讨论线程安全、...

    java 面试题全集 java学习总结

    在Java面试中,面试官通常会考察候选人的基础知识、编程能力、问题解决技巧以及对框架和并发的理解。以下是一些Java面试中常见的知识点: 1. **基础语法**:包括变量、数据类型、运算符、流程控制(如if-else,...

    java常见面试题 面试技巧

    面试官会通过设计模式问题来评估你的设计能力。 十、框架应用 如Spring、MyBatis等,面试中可能会考察你对这些主流框架的理解,包括它们的核心功能、配置方式、AOP、DI等概念。 通过深入学习以上知识点,并结合...

    Java初中级面试常见提问问题总结与回答答案

    在Java初中级面试中,面试官通常会关注应聘者的基础知识掌握程度、编程能力以及对实际问题的解决思路。以下是一些可能遇到的面试问题及其详细的解答,旨在帮助你更好地准备面试,提升成功几率。 1. **Java基础** -...

    java面试大全

    在设计模式方面,面试官可能会询问单例、工厂、观察者、装饰器、代理、策略、模板方法等常见设计模式的应用场景和优缺点。了解并能灵活运用这些设计模式,可以展现出你的代码组织能力和抽象思维。 性能调优也是面试...

    java面试陷阱题

    Java面试是每位求职者在寻找Java相关工作时必须经历的一关,而“陷阱题”则是面试官们常常用来考察候选人深度和广度的一种方式。这些题目往往涉及到一些易被忽视的细节,或者是容易混淆的概念。以下是一些重要的Java...

    张孝祥正在整理Java就业面试题大全(结业版)

    面试官可能会询问内存模型(堆、栈、方法区、本地方法栈),垃圾回收机制(Minor GC、Major GC、Full GC),以及如何进行性能调优。 除此之外,设计模式是衡量一个程序员经验与能力的重要标准。面试中可能会涉及...

    【Java面试题汇总】——超全,建议多次学习,经常复习,常看常新!.rar

    14. **项目经验与问题解决能力**:面试官可能会询问你在过去项目中的角色、遇到的问题以及解决方案,以此评估你的实际工作经验和解决问题的能力。 通过这个Java面试题汇总资源,你可以系统地复习这些知识点,并结合...

    Core Java技术面试资料.doc

    面试中,面试官通常会考察应聘者对Core Java基础知识的掌握程度。以下是一些关于Java核心技术的重要知识点,这些内容通常会在面试中出现: 1. **主方法**: - `main`方法是Java程序的入口点,它的签名是`public ...

    java面试谈薪有敲门.txt.rar

    面试官会通过这些问题评估你的技术水平,这也是决定薪资的重要因素。 2. **框架与项目经验**:熟悉并能灵活运用Spring Boot、MyBatis、Spring Cloud等主流开发框架,以及具备实际项目经验,能够增加你在谈薪时的...

    我的华为面试之旅!!!

    - **技术面试**:技术面试由多位面试官进行,包括理论知识考查和技术实践能力测试。面试过程中会有一些笔试题目,例如编写代码解决特定问题。 - **综合面试**:除了技术方面的考察外,还会评估应聘者的综合素质,...

    Android面试常见问题

    在Android面试中,面试官通常会关注候选人的技术深度、项目经验以及对最新技术趋势的了解。以下是一些常见的Android面试问题,涵盖了多个关键领域: 1. **Android基础知识**: - Android应用架构:理解Activity、...

    华为内部学习材料-面试命题参考书目

    1. **编程基础**:面试官会测试你对基本数据结构(如数组、链表、树、图)和算法(如排序、搜索)的理解和应用能力。这要求你具备扎实的编程语言基础,例如C++、Java或Python,并能够灵活运用这些知识解决问题。 2....

    android面试集锦

    ### Android面试集锦:深入解析核心知识点 #### Intent与Activity通信机制 在Android开发中,`Intent`扮演着至关重要的角色,它不仅用于组件间的数据传递,还是启动新Activity、服务或广播接收器的主要手段。`...

Global site tag (gtag.js) - Google Analytics