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

今天我们不谈单例模式的用途,只说一说如果在面试的时候面试官让你敲一段代码实现单例模式的情况下怎样写出让面试官眼前一亮的单例代码。因为笔者学的是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. APP热更新方案

    为什么要做热更新 当一个App发布之后,突然发现了一个严重bug需要进行紧急修复,这时候公司各方就会忙得焦头烂额:重新打包App.测试.向各个应用市场和渠道换包.提示用户升级.用户下载.覆盖安装. 重 ...

  2. ecshop支付方式含线下自提

    用户展示页面模板所在:如ecshop/theme/default/flow.dwt 后台管理展示页面模板所在:如admin/templates/payment_list.htm ecshop 支付接口 ...

  3. colinux

    Colinux是什么?2004年,由一名21岁的以色列学生与几名日本的自由程序员合作开发出了一个名为“Cooperative Linux”即“CoLinux”的Linux程序,该程 序可使Linux的 ...

  4. SQL储存过程

    基本语法 创建存储过程 create procedure sp_name @[参数名] [类型],@[参数名] [类型] as begin ......... end 以上格式还可以简写成: crea ...

  5. springMVC 配置和使用

    springMVC相对于Struts2学习难度较为简单,并且更加灵活轻便. 第一步:导入jar包 spring.jar.spring-webmvc.jar.commons-logging.jar.sp ...

  6. Facebook开源Zstandard新型压缩算法代替Zlib 简单使用

    简介 Zstandard(缩写为Zstd)是由Facebook的Yann Collet开发的一个无损数据压缩算法.Zstandard在设计上与DEFLATE(.zip.gzip)算法有着差不多的压缩比 ...

  7. GIS与水文分析(1)GIS与水文学

    GIS与水文分析(1)GIS与水文学 对于大部分GIS从业人员或者利用GIS作为研究方向的人员来说,水文学过于专业,更偏重于理论化,很难从GIS的角度来模拟和分析水文的过程.这其实是个普遍性的问题,任 ...

  8. Haoop MapReduce 的Partition和reduce端的二次排序

    先贴一张原理图(摘自hadoop权威指南第三版) 实际中看了半天还是不太理解其中的Partition,和reduce端的二次排序,最终根据实验来结果来验证自己的理解 1eg 数据如下 20140101 ...

  9. zend studio修改字体

    zend studio修改字体 没想到zend studio 9中对中文显示不太好看,似乎有点小了.修改如下:打开Window->Preferences->General->Appe ...

  10. 【LeetCode】237. Delete Node in a Linked List

    题目: Write a function to delete a node (except the tail) in a singly linked list, given only access t ...