亮点面试题&&实现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;

}

}

版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2024-10-28 12:16:50

亮点面试题&&实现Singleton(辛格尔顿)模式-JAVA版本的相关文章

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

单例模式属于创建型模式的一种,创建型模式是一类最常用的设计模式,在软件开发中应用非常广泛.创建型模式将对象的创建和使用分离,在使用对象时无需关心对象的创建细节,从而降低系统的耦合度,让设计方案更易于修改和扩展.每一个创建型模式都在视图回答3个问题:3W -> 创建什么(What).由谁创建(Who)和何时创建(When). 本篇是创建型模式的第一篇,也是最简单的一个设计模式,虽然简单,但是其使用频率确是很高的. 单例模式(Singleton) 学习难度:★☆☆☆☆ 使用频率:★★★★☆ 一.单例

Design Pattern Singleton 单一模式

单一模式的几个注意点: 一) 设计单一模式,首先需要把构造函数给私有化了,不让外界访问,那么外界只能通过提供的函数获取一个新的类. 二) C++的单一模式,记得要在类外初始化一个类,否则或内存出错的. 三) 这个唯一的类必须是要静态的 程序: #ifndef _SINGLETON_H #define _SINGLETON_H #include <iostream> #include <string> using namespace std; class DuGuJiuJian {

设计模式(六):Singleton 单件模式 -- 创建型模式

1.定义 当需要控制一个类的实例数量且调用者可以从一个公共的访问点访问时. 2.适用场景 1. 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时. 2. 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时. 3.评价 优点: 1. 对唯一实例的受控访问, 因为Singleton类封装它的唯一实例,所以它可以严格的控制客户怎样以及何时访问它. 2. 缩小名空间,Singleton模式是对全局变量的一种改进.它避免了那些存储唯一实例的全局变量污染名空

c#单例(Singleton)模式实现

sealed class Singleton { private Singleton(); public static readonly Singleton Instance=new Singleton(); } Singleton类被声明为sealed,以此保证它自己不会被继承,其次没有了Instance的方法,将原来_instance成员变量变成public readonly,并在声明时被初始化.通过这些改变, 我们确实得到了Singleton的模式,原因是在JIT的处理过程中,如果类中的s

【剑指offer】面试题2:实现Singleto模式 java

题目:设计一个类,我们只能生成该类的一个实例. /*一种可行的方式就是采用类级内部类,在这个类级内部类里面去创建对象实例. * 这样一来,只要不使用到这个类级内部类,那就不会创建对象实例, * 从而同时实现延迟加载和线程安全. * */ public class Singleton5 { private Singleton5() {//私有方法确保只创建一个实例 // TODO Auto-generated constructor stub } /** * 类级的内部类,也就是静态的成员式内部类

面试题集锦&amp;&amp;实现Singleton(单例)模式-JAVA版

题目:设计一个类,我们只能生产该类的一个实例.(来自<剑指Offer>) 解析:只能生产一个实例的类是实现Singleton(单例)模式的类型.由于设计模式在面向对象程序设计中起着举足轻重的作业,在面试过程中很多公司都喜欢问一些与设计模式相关的问题.在常用的模式中,Singleton是唯一一个能够用短短几十行代码完整实现的模式.因此,写一个Singleton的类型是一个很常见的面试题. 以下我们给出几种解法,供大家参考. *不好的解法一:只适用于单线程环境. 由于要求只能产生一个实例,因此我们

Item 3 - What is an efficient way to implement a singleton pattern in Java?

Depending on the usage, there are several "correct" answers. Since java5 the best way to do it is to use an enum: public enum Foo { INSTANCE; } The Right Way to Implement a Serializable Singleton public enum Elvis { INSTANCE; private final Strin

【java设计模式】之 单例(Singleton)模式

1. 单例模式的定义 单例模式(Singleton Pattern)是一个比较简单的模式,其原始定义如下:Ensure a class has only one instance, and provide a global point of access to it. 即确保只有一个实例,而且自行实例化并向整个系统提供这个实例.单例模式的通用类如下图所示: Singleton类称为单例类,通过使用private的构造函数确保了在一个应用中只产生一个实例,并且是自行实例化的(在Singleton中

使用单态(Singleton)模式获取数据库操作对象

开始先介绍下单态模式,也就是单例模式,我们主要区别于Spring中的原型模式,单例模式就是保证一个类只存在一个实例,就是只初始化一次,第一次完成初始化以后,重复使用的时候,返回的都是这个实例,而且不是重新去new一个新的,这就在DAO层中比较常见,我们定义一个工厂类(seesionFactory),不用每次都去New个用,好处在于节省了内存和时间,但是如果你对象里面的属性值已经改变的话,就不适合使用单例了,只能重新New个,我们一般的用法Spring的Action层就是使用这个原型,可以创建多次