亮点面试题&&实现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 ...
随机推荐
- 颜色(color)转换为三刺激值(r/g/b)(干股)
//颜色转换 ##665522 - 三色值 + (UIColor *)setFontColorWithString:(NSString *)color { NSString *cString ...
- Canvas的quadraticCurveTo 和 bezierCurveTo 画曲线 方法细说
详细代码如下: <!doctype html> <html lang="en"> <head> <script src="htt ...
- 数据结构:循环队列(C语言实现)
生活中有非常多队列的影子,比方打饭排队,买火车票排队问题等,能够说与时间相关的问题,一般都会涉及到队列问题:从生活中,能够抽象出队列的概念,队列就是一个能够实现"先进先出"的存储结 ...
- Android使用代码消除App数据并重新启动设备
/** * 使用代码消除App数据 * 我们不寻常的清除App数据,中找到相应的App * 然后选择其清除数据.以下给出代码实现. * * 注意事项: * 1 设备须要root * 2 该演示样例中删 ...
- ACdream 1427 Nice Sequence
主题链接:http://115.28.76.232/problem? pid=1427 Nice Sequence Time Limit: 12000/6000MS (Java/Others)Memo ...
- spring交易声明的几个传播特性
近期遇到了一个spring事务导致的问题,所以写了几个小程序了解了一下事务的传播特性,以下分别举样例分别看看事务的传播特性. 事务的几种传播特性 1. PROPAGATION_REQUIRED: 假设 ...
- SharePoint 2013 配置开发环境,需安装VS2012插件
原文:SharePoint 2013 配置开发环境,需安装VS2012插件 SharePoint 2013已经安装好了,接下来就是配置开发环境,安装VS2012,但是,装好了以后,发现没有ShareP ...
- NSIS:超级轻量皮肤SkinH
原文 NSIS:超级轻量皮肤SkinH 这虽然是一个其他软件的皮肤控件,不过拿来用到NSIS上还是不错的.控件加皮肤文件只有100多K,可以说是比较难得了! 看一下效果: 代码示例: 01 #皮肤 ...
- Controller 里面就只应该存放这些不能复用的代码(转)
MVC 的历史 MVC,全称是 Model View Controller,是模型 (model)-视图 (view)-控制器 (controller) 的缩写.它表示的是一种常见的客户端软件开发框架 ...
- JavaEE(10) - Session EJB的依赖注入、引用及任务调度
1. EJB依赖注入 #1. EJB开发(Net Beans创建EJB Module, 项目名称:CallHello) Hello.java package org.crazyit.service; ...