亮点面试题&&实现Singleton(辛格尔顿)模式-JAVA版本
称号:设计一个类。我们只能产生这个类的一个实例。(来自《剑指Offer》)
解析:仅仅能生产一个实例的类是实现Singleton(单例)模式的类型。因为设计模式在面向对象程序设计中起着举足轻重的作业,在面试过程中非常多公司都喜欢问一些与设计模式相关的问题。
在经常使用的模式中,Singleton是唯一一个可以用短短几十行代码完整实现的模式。
因此,写一个Singleton的类型是一个非经常见的面试题。
下面我们给出几种解法。供大家參考。
*不好的解法一:仅仅适用于单线程环境。
因为要求仅仅能产生一个实例。因此我们必须把构造函数设为私有函数以禁止他人创建实例。我们能够定义一个静态的实例,在须要的时候创建该实例。基于这个思路的实现:
public class Singleton1{
private Singleton1(){
}
private final static Singleton1 instance = null;
public static Singleton1 getInstance(){
if(instance == null)
instance = new Singleton1();
return instance;
}
}
上述代码在Singleton1的静态属性Instance中,仅仅有在instance为null的时候才创建一个实例以避免反复创建。同一时候。我们把构造函数定义为私有函数,这样就能确保仅仅创建一个实例。
*不好的解法二:尽管在多线程环境中能工作但效率不高
解法一中的代码在单线程的时候工作正常。但在多线程的情况下就有问题了。设想假设两个线程同一时候执行到推断instance是否为null的if语句。而且instance的确没有创建时,那么两个线程都会创建一个实例,此时类型Singleton1就不再满足单例模式的要求了。
为了保证在多线程环境下我们还是仅仅能得到类型的一个实例,须要加上一个同步锁。把Singleton1稍做改动得到了例如以下代码:
public class Singleton2 {
private static Singleton2 instance = null;
private Singleton2() { }
public static synchronized Singleton2 getInstance() {
if(instance == null) {
instance = new Singleton2();
}
return instance;
}
}
我们还是如果有两个线程同一时候想创建一个实例。因为在一个时刻仅仅有一个线程能得到同步锁。当第一个线程加上锁时,第二个线程仅仅能等待。当第一个线程发现实例还没有创建时,它创建出一个实例。接着第一个线程释放同步锁,此时第二个线程能够加上同步锁,并执行接下来的代码。这个时候因为实例已经被第一个线程创建出来了,第二个线程就不会反复创建实例了,这样就保证了我们在多线程环境中也仅仅能得到一个实例。
可是类型Singleton2还不是非常完美。我们每次通过属性Instance得到Singleton2的实例,都会试图加上一个同步锁,而加锁是一个非常耗时的操作。在没有必要的时候我们应该尽量避免。
**可行的解法一:加同步锁前后两次推断实例是否已存在
我们仅仅是在实例还没有创建之前须要加锁操作,以保证仅仅有一个线程创建实例。而当实例已经创建之后,我们已经不须要再加锁操作了。所以我们改进例如以下:
public class Singleton3 {
private static Singleton3 instance = null;
private Singleton3() { }
public static Singleton3 getInstance() {
if(instance == null) {
synchronzied(Singleton3.class) {
Singleton3 temp = instance;
if(temp == null) {
temp = new Singleton3();
instance = temp
}
}
}
return instance;
}
}
因为指令重排序问题,所以不能够直接写成以下这样:
public class Singleton3 {
private static Singleton3 instance = null;
private Singleton3() { }
public static Singleton3 getInstance() {
if(instance == null) {
synchronzied(Singleton3.class) {
if(instance == null) {
instance = new Singleton3();
}
}
}
return instance;
}
}
可是假设instance实例变量用volatile修饰就能够了,volatile修饰的话就能够确保instance = new Singleton();相应的指令不会重排序,例如以下的单例代码也是线程安全的:
public class Singleton3 {
private static volatile Singleton3 instance = null;
private Singleton3() { }
public static Singleton3 getInstance() {
if(instance == null) {
synchronzied(Singleton3.class) {
if(instance == null) {
instance = new Singleton3();
}
}
}
return instance;
}
}
Singleton3用加锁机制来确保在多线程环境下仅仅创建一个实例,而且用俩个if推断来提高效率。
这种代码实现起来比較复杂,easy出错,我们还有更优秀的解法。
**强烈推荐的解法二:借助内部类
这样的方法属于懒汉式单例,由于Java机制规定,内部类SingletonHolder仅仅有在getInstance()方法第一次调用的时候才会被载入(实现了lazy)。并且其载入过程是线性安全的。内部类载入的时候实例化一次instance。
public class Singleton {
private Singleton() { }
private static class SingletonHolder {
private final static Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
版权声明:本文博客原创文章,博客,未经同意,不得转载。
亮点面试题&&实现Singleton(辛格尔顿)模式-JAVA版本的更多相关文章
- 剑指offer之面试题2:实现Singleton模式
来源:剑指offer 这篇主要记录<剑指offer>书籍中的面试题2:实现Singleton模式 使用语言:C# 代码环境:VS2017 总共有5中解法,从前往后依次优化. 结构如下: 前 ...
- 《剑指offer》面试题2:实现Singleton 模式
面试题2:实现Singleton 模式 题目:设计一个类,我们只能生成该类的一个实例. 只能生成一个实例的类是实现了Singleton (单例)模式的类型.由于设计模式在面向对象程序设计中起着举足 ...
- 小菜学习设计模式(二)—单例(Singleton)模式
前言 设计模式目录: 小菜学习设计模式(一)—模板方法(Template)模式 小菜学习设计模式(二)—单例(Singleton)模式 小菜学习设计模式(三)—工厂方法(Factory Method) ...
- 设计模式的征途—1.单例(Singleton)模式
单例模式属于创建型模式的一种,创建型模式是一类最常用的设计模式,在软件开发中应用非常广泛.创建型模式将对象的创建和使用分离,在使用对象时无需关心对象的创建细节,从而降低系统的耦合度,让设计方案更易于修 ...
- 转载 单例(Singleton)模式)的误区
在创建型模式中,单例(Singleton)模式和原型(Prototype)模式相对来说其用意更为简单明了.单例(Singleton)模式确保某类只有一个实例,且自行实例化并向整个系统提供这个实例:原型 ...
- c#单例(Singleton)模式实现
sealed class Singleton { private Singleton(); public static readonly Singleton Instance=new Singleto ...
- 创建对象——单例(Singleton)模式
单例(Singleton)模式: 保证一个类在系统里只能有一个对象被实例化. 如:缓存池.数据库连接池.线程池.一些应用服务实例等. 难点:在多线程环境中,保证实例的唯一性. ...
- 剑指Offer面试题:1.实现Singleton模式
说来惭愧,自己在毕业之前就该好好看看<剑指Offer>这本书的,但是各种原因就是没看,也因此错过了很多机会,后悔莫及.但是后悔是没用的,现在趁还有余力,把这本书好好看一遍,并通过C#通通实 ...
- 剑指Offer-【面试题02:实现Singleton 模式——七种实现方式】
题目:设计一个类,我们只能生成该类的一个实例 package com.cxz.demo02; /** * Created by CXZ on 2016/9/13. */ public class Si ...
随机推荐
- Codefoces 432 C. Prime Swaps
哥德巴赫猜想: 任一大于2的偶数,都可表示成两个素数之和. 任一大于5的整数都可写成三个质数之和. 贪心取尽可能大的素数..... C. Prime Swaps time limit per test ...
- Windows store 验证你的 URL http:// 和 https:// ms-appx:/// ms-appdata:///local
前缀 使用 注意事项 http:// 和 https:// 联机存储的图像 这些图像可能缓存在本地,因此图像服务器可能未收到图像的请求.可以在这些 URL 中附加查询字符串.确保 Web 服务器返回原 ...
- Mapxtreme C#鹰眼地图
Demo演示程序下载地址: http://pan.baidu.com/s/1jG9gKMM#dir/path=%2F%E4%BA%A7%E5%93%81%2FDemos 找:EagelEyeMap.r ...
- ios animation暂停pause、恢复resume
项目以使用来控制动画,例如暂停.复苏继续等待,看看代码:(非常easy实现) -(void)pauseLayer:(CALayer*)layer { CFTimeInterval pausedTime ...
- 浅析Java中的final关键字(转)
谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法.下 ...
- Properties类读写.properties配置文件
package com.hzk.utils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFo ...
- CI框架学习笔记
打印SQL语句$this->dbRead->last_query(); 重映射方法正如上文所说,URI 的第二段通常决定控制器的哪个方法被调用.CodeIgniter 允许你使用 _rem ...
- 30分钟让你了解MongoDB基本操作(转)
今天记录下MongoDB的基本操作,这只是最基本的,所以是应该掌握的. 数据库 数据库是一个物理容器集合.每个数据库都有自己的一套文件系统上的文件.一个单一的MongoDB服务器通常有多个数据库. 集 ...
- Oracle 11g+oracle客户端(32位)+PL/SQL develepment的安装配置
之前一直想学Oracle,可是就是安装配置Oracle一直未成功,让人很苦恼,特别是什么监听器什么的,一直没搞明白,弄了整整一天都没弄出来,上网查资料后发现资料上大多数都是参差不齐,不太详细明了,尝试 ...
- ORA-07445: :一个意料之外的问题发生了 核心转储 [ldxsnf()+625] [SIGSEGV
ALERT登录错误消息: Mon Jan 20 15:03:22 2014 Incremental checkpoint up to RBA [0x442f.abd.0], current log t ...