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

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

    同步自我的知乎专栏:https://zhuanlan.zhihu.com/p/27343585 本文完整代码地址:Generative Adversarial Networks (GANs) with ...

  2. android 下 利用webview实现浏览器功能

    android 下 利用webview实现浏览器功能(一): 1.界面添加WEBVIEW控件. 2.在界面.JAVA代码页面(protected void onCreate(Bundle savedI ...

  3. IIS虚拟目录与UNC路径权限初探

    最近在一个项目中涉及到了虚拟目录与UNC路径的问题,总结出来分享给大家. 问题描述 某客户定制化项目(官网),有一个图片上传的功能.客户的Web机器有10台,通过F5负载均衡分摊请求. 假设这10台机 ...

  4. centos ios镜像文件 安装详细

    1.挂载iOS镜像(先打开VM 选择虚拟机---->设置-->CD ---->使用ISO镜像文件 用浏览打开) 2.开始界面选择 3出现下面的界面 这是提示你是否扫描文件的完整性 我 ...

  5. $.Deferred 延迟对象

    一.什么是deferred对象? 开发网站的过程中,我们经常遇到某些耗时很长的javascript操作.其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们 ...

  6. JAVAEE——spring02:使用注解配置spring、sts插件、junit整合测试和aop演示

    一.使用注解配置spring 1.步骤 1.1 导包4+2+spring-aop 1.2 为主配置文件引入新的命名空间(约束) 1.3 开启使用注解代替配置文件 1.4 在类中使用注解完成配置 2.将 ...

  7. linux开机启动smb服务

    修改/etc/rc.local文件(增加红色部分) [root@localhost ~]# cat /etc/rc.local #!/bin/sh## This script will be exec ...

  8. php检测当前浏览器是否为微信浏览器

    <?php /** php检测当前浏览器是否为微信浏览器 */ function is_weixin_browser(){ if(strpos($_SERVER['HTTP_USER_AGENT ...

  9. Linux系统目录结构介绍

    参考博客: http://www.cnblogs.com/chensiqiqi/p/6243549.html 感谢原博主为我学习Linux指明方向!! linux目录:一切从“根”开始,“/”是所有目 ...

  10. accp8.0转换教材第9章JQuery相关知识理解与练习

    自定义动画 一.单词部分: ①animate动画②remove移除③validity有效性 ④required匹配⑤pattern模式 二.预习部分 1.简述JavaScript事件和jquery事件 ...