称号:设计一个类。我们只能产生这个类的一个实例。(来自《剑指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版本的更多相关文章

  1. 剑指offer之面试题2:实现Singleton模式

    来源:剑指offer 这篇主要记录<剑指offer>书籍中的面试题2:实现Singleton模式 使用语言:C# 代码环境:VS2017 总共有5中解法,从前往后依次优化. 结构如下: 前 ...

  2. 《剑指offer》面试题2:实现Singleton 模式

    面试题2:实现Singleton 模式 题目:设计一个类,我们只能生成该类的一个实例.   只能生成一个实例的类是实现了Singleton (单例)模式的类型.由于设计模式在面向对象程序设计中起着举足 ...

  3. 小菜学习设计模式(二)—单例(Singleton)模式

    前言 设计模式目录: 小菜学习设计模式(一)—模板方法(Template)模式 小菜学习设计模式(二)—单例(Singleton)模式 小菜学习设计模式(三)—工厂方法(Factory Method) ...

  4. 设计模式的征途—1.单例(Singleton)模式

    单例模式属于创建型模式的一种,创建型模式是一类最常用的设计模式,在软件开发中应用非常广泛.创建型模式将对象的创建和使用分离,在使用对象时无需关心对象的创建细节,从而降低系统的耦合度,让设计方案更易于修 ...

  5. 转载 单例(Singleton)模式)的误区

    在创建型模式中,单例(Singleton)模式和原型(Prototype)模式相对来说其用意更为简单明了.单例(Singleton)模式确保某类只有一个实例,且自行实例化并向整个系统提供这个实例:原型 ...

  6. c#单例(Singleton)模式实现

    sealed class Singleton { private Singleton(); public static readonly Singleton Instance=new Singleto ...

  7. 创建对象——单例(Singleton)模式

      单例(Singleton)模式:   保证一个类在系统里只能有一个对象被实例化.   如:缓存池.数据库连接池.线程池.一些应用服务实例等.   难点:在多线程环境中,保证实例的唯一性.     ...

  8. 剑指Offer面试题:1.实现Singleton模式

    说来惭愧,自己在毕业之前就该好好看看<剑指Offer>这本书的,但是各种原因就是没看,也因此错过了很多机会,后悔莫及.但是后悔是没用的,现在趁还有余力,把这本书好好看一遍,并通过C#通通实 ...

  9. 剑指Offer-【面试题02:实现Singleton 模式——七种实现方式】

    题目:设计一个类,我们只能生成该类的一个实例 package com.cxz.demo02; /** * Created by CXZ on 2016/9/13. */ public class Si ...

随机推荐

  1. error C2871: &#39;std&#39; : does not exist or is not a namespace

    #include <iostream.h> using namespace std; 然后编译时出现 error C2871: 'std' : does not exist or is n ...

  2. Cocos2dx 3.0 过渡篇(二十五)死不了的贪食蛇(触摸版)

    上一篇写的贪食蛇的重力感应控制版,这一篇就讲下触摸控制版吧.额,也不知道写了那个贪食蛇教程究竟有没有获得沈老师的书,假设没有的话,看我不拿西瓜刀砍掉 偶尔E往事 的那啥! 重力版链接:http://b ...

  3. 通达OA web页面与精灵显示内容更新后不一致的问题

    前一段就发现有这种问题.就是在开发的电话查询里更新的信息,可是在精灵对话窗体上显示的还是原来的信息.这样导致从新开发入口更新信息就不能使用.一開始还以为是厂家升级,变更了存储的表结构.感觉下载近期的升 ...

  4. 银联+移动+三星PK微信、余额宝

    在不远的将来,你可以扔掉钱包,扔掉信用卡,揣着手机买东西. 银联.移动.三星这些不同的行业大佬,因为这个目标,被一款名叫NFC的支付技术连接在了一起. 这场游戏的参与者众多,一个合纵连横的时代正在到来 ...

  5. Redux基础

    Redux 是一个状态容器 Redux 就像是作者自己的介绍,它不会为你提供任何的东西,它不会告诉你如何做路由,它只专注于应用程序状态,是一个 JavasSript 的状态容器,所有的状态的变化都是当 ...

  6. Android一些解决方案内存问题(一)

    通常我们遇到内存问题时,,解决方案一般有以下的例子: 1.做一些处理上的内存引用,经常使用软引用.加强引用.弱引用: 2.加载在内存中的照片时,它可以处理直接在内存,例如:压缩边界. 3.内存的动态恢 ...

  7. rabbitMQ说明文档

    rabbitMQ是什么 RabbitMQ     是由     LShift     提供的一个     Advanced Message Queuing Protocol (AMQP)     的开 ...

  8. ArcGIS JavaScript API本地部署离线开发环境[转]

    原文地址:http://www.cnblogs.com/brawei/archive/2012/12/28/2837660.html 1 获取ArcGIS JavaScript API API的下载地 ...

  9. Ajax.BeginForm的异步提交数据 简介

    Html.BeginForm与Ajax.BeginForm都是MVC架构中的表单元素,它们从字面上可以看到区别,即Html.BeginForm是普通的表单提交,而Ajax.BeginForm是支持异步 ...

  10. SQL字符串转换为数组

    /*一.按指定符号分割字符串,返回分割后的元素个数,方法很简单,就是看字符串中存在多少个分隔符号,然后再加一,就是要求的结果. -----rtrim(@str)去掉 @str右边的字符 ltrim(@ ...