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

今天我们不谈单例模式的用途,只说一说如果在面试的时候面试官让你敲一段代码实现单例模式的情况下怎样写出让面试官眼前一亮的单例代码。因为笔者学的是Java,所以接下来的实例将用Java语言编写。

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

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

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

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

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

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

如何理解呢?

  1. 线程 1 进入get 方法。

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

  3. 线程 1 被线程 2 预占。

  4. 线程 2 进入get 方法。

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

  6. 线程 2 被线程 1 预占。

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

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

  9. 线程 1 被线程 2 预占。

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

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

像这样的程序,面试官看完还能不给你offer吗?骚年,前途不可限量啊!

如何写出面试官欣赏的Java单例的更多相关文章

  1. 最后一面挂在volatile关键字上,面试官:重新学学Java吧!

    最后一面挂在volatile关键字上,面试官:重新学学Java吧! 为什么会有volatile关键字? volatile: 易变的; 无定性的; 无常性的; 可能急剧波动的; 不稳定的; 易恶化的; ...

  2. 【JAVA秒会技术之秒杀面试官】秒杀Java面试官——集合篇(一)

    [JAVA秒会技术之秒杀面试官]秒杀Java面试官——集合篇(一) [JAVA秒会技术之秒杀面试官]JavaEE常见面试题(三) http://blog.csdn.net/qq296398300/ar ...

  3. 熟悉的味道——从Java单例写到C++单例

    设计模式中,单例模式是常见的一种.单例模式需要满足以下两个条件: 保证一个类只能创建一个示例: 提供对该实例的全局访问点. 关于单例最经典的问题就是DCL(Double-Checked Lock),今 ...

  4. java单例-积木系列

    一步步知识点归纳吧,把以前似懂非懂,了解表面,知道点不知道面的知识归一下档.   懒汉式单例: 私有化构造函数,阻止外界实例话对象,调用getInstance静态方法,判断是否已经实例化. 为什么是懒 ...

  5. 转:java单例设计模式

    本文转自:http://www.cnblogs.com/yinxiaoqiexuxing/p/5605338.html 单例设计模式 Singleton是一种创建型模式,指某个类采用Singleton ...

  6. Java单例类的简单实现

    对于java新手来说,单例类给我的印象挺深,之前一道web后台笔试题就是写单例类.*.*可惜当时不了解. 在大部分时候,我们将类的构造器定义成public访问权限,允许任何类自由创建该类的对象.但在某 ...

  7. 【Java学习笔记之三十】详解Java单例(Singleton)模式

    概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...

  8. java单例的几种写法

    转载出处:http://cantellow.javaeye.com/blog/838473 第一种(懒汉,线程不安全): public class Singleton { private static ...

  9. java单例五种实现模式梳理

    java单例五种实现模式 饿汉式(线程安全,调用效率高,但是不能延时加载) 一上来就把单例对象创建出来了,要用的时候直接返回即可,这种可以说是单例模式中最简单的一种实现方式.但是问题也比较明显.单例在 ...

随机推荐

  1. Spring学习(1)----入门学习(附spring-framework下载地址)

    (一)Spring是什么 Spring是一个开源框架,为了解决企业应用开发的复杂性而创建的,但现在已经不止应用于企业应用 是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架- 从大小和开销 ...

  2. JavaScript数组基础及实例

    js数组 和var i=1;这样的简单存储一样是js中的一种数据结构,是专门用来存储多个数据的一种数据结构. 摘:数组是一组数据的集合,其表现形式就是内存中的一段连续的内存地址,数组名称其实就是连续内 ...

  3. SQLServer类型与Java类型转换问题解决

    ResultSet 接口提供用于从当前行获取列值的获取 方法(getBoolean.getLong 等).可以使用列的索引编号或列的名称获取值.一般情况下,使用列索引较为高效.列从 1 开始编号.为了 ...

  4. 20170422早会训话,ps:程序出现两次BUG,领导很生气

    针对这种问题: 要讲3点 1.有没有拖团队后腿: 作为一名前端开发人员,对于前端开发的任务,我能够在第一时间完成,保证时间进度,但光做到这一点是不够的,不能只讲究任务,不考虑结果,会不会出现问题造成其 ...

  5. Zabbix 3.2.6安装过程

    以3.2.6版本的Zabbix为例展开说明 1.准备Lnmp环境. 本次准备的环境: Linux:2.6.32-642.el6.x86_64 Nginx:1.12.0 Mariadb:10.2.6 P ...

  6. 设置Ubuntu下adb 及 fastboot权限

    以普通用户登录linux,然后运行adb devices会提示权限不够: List of devices attached  ????????????    no permissions   这是因为 ...

  7. 数据的ID名生成新的引用索引树

    <?php $arr= [ '0'=>[ "id"=>2, "name"=>"建材", "pid" ...

  8. 生成一个唯一token

    $token = md5(uniqid(rand(), true));

  9. Spring配置注解详解

  10. 手把手教你 基础 整合最优雅SSM框架:SpringMVC + Spring

    我们看招聘信息的时候,经常会看到这一点,需要具备SSH框架的技能:而且在大部分教学课堂中,也会把SSH作为最核心的教学内容. 但是,我们在实际应用中发现,SpringMVC可以完全替代Struts,配 ...