面试题集锦&&实现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判断来提高效率。这样的代码实现起来比较复杂,容易出错,我们还有更优秀的解法。

**强烈推荐的解法二:借助内部类

这种方法属于懒汉式单例,因为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-11 22:17:55

面试题集锦&&实现Singleton(单例)模式-JAVA版的相关文章

Singleton(单例)模式

Singleton(单例)模式用于确保某个类只有一个实例,并且为之提供一个全局访问点. Singleton模式适用情况: 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时 在任何情况下,Singleton模式都建议我们提供能够访问单例对象的公有静态方法.如果使用这个方法创建一个对象,该方法将承担确保仅创建一个实例的责任. Singleton 定义一个Instance操作,允许客户访问它的唯一实例

javascript设计模式-singleton(单例)模式

singleton(单例)模式被熟知的原因是因为它限制了类的实例化次数只能一次,单例模式,在该实例不存在的勤快下,可以通过一个方法创建一个类来实现创建类的新实例:如果实例已经存在,则会简单返回该对象的引用.单例模式不同于静态类(或对象),因为我们可以推迟它们的初始化,这通常是因为它需要一些信息,而这些信息在初始化期间可能无法获取,对于没有察觉到之前的引用代码,它们不会提供方便检索方法,这是因为它既不是对象,也不是由一个single返回的类,而是一个结构,在js中,singleton充当共享资源命

Java设计模式:Singleton(单例)模式

概念定义 Singleton(单例)模式是指在程序运行期间, 某些类只实例化一次,创建一个全局唯一对象.因此,单例类只能有一个实例,且必须自己创建自己的这个唯一实例,并对外提供访问该实例的方式. 单例模式主要是为了避免创建多个实例造成的资源浪费,以及多个实例多次调用容易导致结果出现不一致等问题.例如,一个系统只能有一个窗口管理器或文件系统,一个程序只需要一份全局配置信息. 应用场景 资源共享的情况下,避免由于资源操作时导致的性能或损耗等.如缓存.日志对象.应用配置. 控制资源的情况下,方便资源之

从别人写的 Object-C 中 Singleton (单例) 模式 中的一些理解--备

关于 面向对象的设计模式 对于面向对象的设计模式,想必大家并不陌生吧. 纵观23种设计模式中,数单例模式(Singleton)和工厂模式(Factory Method)最为熟悉和基础吧.当然,本文总结Singleton模式,对于其他设计模式不做叙说. Singleton模式,即单例模式.顾名思义,主要用于做应用程序的资源共享控制.用途很多?? 实质为,单例是在程序声明周期里 有且仅有 被实例化过一次的类.为确保实例化的唯一,利用类的 类(static)方法来生成和访问对象. 至此,你便可以在程序

C++ Singleton (单例) 模式最优实现

参考:http://blog.yangyubo.com/2009/06/04/best-cpp-singleton-pattern/ 索引 静态化并不是单例 (Singleton) 模式 饿汉模式 懒汉模式 (堆栈-粗糙版) 懒汉模式 (局部静态变量-最佳版) 范例代码和注意事项 (最优实现) 扩展阅读 参考资料 我非常赞成合理的使用 设计模式 能让代码更容易理解和维护, 不过我自己除了简单的 单例 (Singleton) 模式 外, 其它都很少用 :-) 可耻的是, 直到前段时间拜读了 C++

[Java设计模式](一)怎样实现Singleton(单例)模式编程

单例模式是开发模式中最简单,最易于理解的一种模式.简单地说,它指的就是始终保持一个实例的意思.但是,Java的类是可以穿件多个实例的,那么,怎么实现呢? 顾名思义,单例模式就是只有一个实例.单例模式确保某一个类只有一个实例,这个类称为单例类,单例模式有3个要点: ①是某个类只能有一个实例: ②它必须自行创建这个实例: ③是它必须自行向整个系统提供这个实例.例如,一些资源管理器常常设计成单例模式. 在计算机系统中,需要管理的资源有很多,例如每台计算机可以有若干个打印机,但只能有一个打印控制器,以避

[java]设计模式之singleton(单例)

在日常工作中,有很多对象,我们只需要一个.比如:线程池, 缓存,注册表等.如果制造出多个实例,就会导致许多问题,如程序行为异常,资源使用过量等.这就需要对对象的构建进行控制,使其只能产生一个对象.这就是本篇要讲的设计模式--singleton(单例). 单例模式的定义:确保只有一个类只有一个实例,并提供一个全局访问点. 那么,要如何实现单例模式,使得一个类只能产生一个对象呢?请看下面的实现: public class Singleton { private static Singleton s;

lintcode 容易题 :Singleton 单例

题目: 单例 单例是最为最常见的设计模式之一.对于任何时刻,如果某个类只存在且最多存在一个具体的实例,那么我们称这种设计模式为单例.例如,对于 class Mouse (不是动物的mouse哦),我们应将其设计为 singleton 模式. 你的任务是设计一个 getInstance 方法,对于给定的类,每次调用 getInstance 时,都可得到同一个实例.  样例 在 Java 中:A a = A.getInstance(); A b = A.getInstance(); a 应等于 b.

Singleton 单例模板

1 // singleton.h 2 3 #ifndef SINGLETON_H 4 #define SINGLETON_H 5 6 // 单例基类模板 7 template <class T> 8 class Singleton 9 { 10 public: 11 static T& give_me() 12 { 13 static T s_inst; 14 return s_inst; 15 } 16 17 private: 18 // 禁止实现拷贝构造与拷贝赋值函数 19 exp