Design Pattern —— Singleton   强力推荐枚举和类级内部类方式实现单例模式

单例模式是开发中非常常用的一种模式,简单的说,我们希望一个类永远都只有一个对象。

主要有两个用途:

1.存储一些进程内共享的值(不是很推荐,大部分情况下还是应该用局部变量,互相传递值的方式)

2.任何时候都不变的操作

单例模式的实现目前已知的有五种:

1.饿汉式

2.懒汉式

3.双重验证

4.类级内部类

5.枚举

一、饿汉式

类加载时就创建好对象,以空间换时间。这样外部调用EagerSingleton.getInstance()时,直接获得这个创建好的对象。

 public class EagerSingleton {
private static EagerSingleton instance = new EagerSingleton();
/**
* 私有默认构造子
*/
private EagerSingleton(){}
/**
* 静态工厂方法
*/
public static EagerSingleton getInstance(){
return instance;
}
}

优点:节省运行时间

缺点:占用空间

二、懒汉式

类加装时不创建对象,直到需要使用时才创建。

 public class LazySingleton {
private static LazySingleton instance = null;
/**
* 私有默认构造子
*/
private LazySingleton(){}
/**
* 静态工厂方法
*/
public static synchronized LazySingleton getInstance(){
if(instance == null){
instance = new LazySingleton();
}
return instance;
}
}

优点:节省空间,如果一直不用,就不会创建

缺点:每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间。且是由于是线程安全的,所以会降低整体的访问速度

三、双重验证

双重验证的单例模式,是懒汉式单例的一种优化方式。既实现线程安全,又能够使性能不受很大的影响。

定义:

1.先不同步,进入方法后,先检查实例是否存在,如果不存在才进行下面的同步块,这是第一重检查;

2.进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。

这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。

  “双重检查加锁”机制的实现会使用关键字volatile,简单的说:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。

 public class Singleton {
private volatile static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
//先检查实例是否存在,如果不存在才进入下面的同步块
if(instance == null){
//同步块,线程安全的创建实例
synchronized (Singleton.class) {
//再次检查实例是否存在,如果不存在才真正的创建实例
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}

双重验证的方式虽然看上去很美,但是是不被推荐使用的。具体volatile的使用也是一个比较大的课题,有一篇非常好的文章推荐http://www.cnblogs.com/dolphin0520/p/3920373.html

四、类级内部类实现的方式。

那我们能不能想到一个办法,既让第一次使用时才创建对象,又解决线程安全呢。

类级内部类的特点:

1.类级内部类的对象和外部类对象没有依赖关系

2.类级内部类中可以有静态方法,此静态方法只能调用外部类的静态方法和成员变量

3.类级内部类只有在第一次使用时才会加载

JVM在有些时候会隐式的去执行同步操作:

1.由静态初始化器(在静态字段上或static{}块中的初始化器)初始化数据时

2.访问final字段时

3.在创建线程之前创建对象时

4.线程可以看见它将要处理的对象时

实现线程安全:可以采用静态初始化器的方式,它可以由JVM来保证线程的安全性。

实现延迟加载:采用类级内部类,在这个类级内部类里面去创建对象实例。只要不使用到这个类级内部类,那就不会创建对象实例。

 public class Singleton {

     private Singleton(){}
/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
* 没有绑定关系,而且只有被调用到时才会装载,从而实现了延迟加载。
*/
private static class SingletonHolder{
/**
* 静态初始化器,由JVM来保证线程安全
*/
private static Singleton instance = new Singleton();
} public static Singleton getInstance(){
return SingletonHolder.instance;
}
}

五、枚举实现单例

《effectJava》一书中重点推荐的实现单例的方式

 public enum Singleton {
/**
* 定义一个枚举的元素,它就代表了Singleton的一个实例。
*/ uniqueInstance; /**
* 单例可以有自己的操作
*/
public void singletonOperation(){
//功能处理
}
}

枚举单例,简洁,提供序列化机制,防止多实例化,防止反射,是实现单例的最佳方案。

参考资料

http://www.cnblogs.com/dolphin0520/p/3920373.html  violate详解

http://www.cnblogs.com/java-my-life/archive/2012/03/31/2425631.html  java与模式之单例模式

《effectJava》

Design Pattern —— Singleton的更多相关文章

  1. [Design Pattern] Singleton Pattern 简单案例

    Singleton Pattern, 即单例模式,用于获取类的一个对象,该对象在整个应用中是其类的唯一对象.单例模式属于创建类的设计模式. SingleObject 作为单例类,内含了一个静态私有的 ...

  2. (Design Pattern) Singleton.

    Role: The purpose of the Singleton pattern is to ensure that there is only one instance of a class, ...

  3. Design Pattern Singleton 单一模式

    单一模式的几个注意点: 一) 设计单一模式,首先须要把构造函数给私有化了,不让外界訪问,那么外界仅仅能通过提供的函数获取一个新的类. 二) C++的单一模式,记得要在类外初始化一个类,否则或内存出错的 ...

  4. python singleton design pattern super() 多继承

    python  singleton design pattern decorate baseclass metaclass import module super() 一.A decorator de ...

  5. 说说设计模式~大话目录(Design Pattern)

    回到占占推荐博客索引 设计模式(Design pattern)与其它知识不同,它没有华丽的外表,没有吸引人的工具去实现,它是一种心法,一种内功,如果你希望在软件开发领域有一种新的突破,一个质的飞越,那 ...

  6. 设计模式(Design Pattern)系列之.NET专题

    最近,不是特别忙,重新翻了下设计模式,特地在此记录一下.会不定期更新本系列专题文章. 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用 ...

  7. [转]Design Pattern Interview Questions - Part 4

    Bridge Pattern, Composite Pattern, Decorator Pattern, Facade Pattern, COR Pattern, Proxy Pattern, te ...

  8. [转]Design Pattern Interview Questions - Part 1

    Factory, Abstract factory, prototype pattern (B) What are design patterns? (A) Can you explain facto ...

  9. Null Object Design Pattern (Python recipe)

    Null Object 个人感觉非常有用.也是在review公司其他同事写代码的时候看到. 当时使用了flask的request全局请求变量g,然后使用了g.x保存了一个东西. 当时在view代码读取 ...

随机推荐

  1. mapreduce (七) 几个实例

    http://hi.baidu.com/hzd2712/item/d2465ae65270ab3e4cdcaf55 MapReduce几个典型的例子 在Google的<MapReduce: Si ...

  2. Delphi控件的透明与不透明(要挨个解释一下原因),对InvalidateControl的关键理解

    procedure TForm1.Button3Click(Sender: TObject);begin if (csOpaque in ControlStyle) then ShowMessage( ...

  3. Linux Shell脚本Ldd命令原理及使用方法

    1.首先ldd不是一个可执行程序,而只是一个shell脚本2.ldd能够显示可执行模块的dependency,其原理是通过设置一系列的环境变量如下:LD_TRACE_LOADED_OBJECTS.LD ...

  4. github Travis CI 持续集成

    一个项目如何保证代码质量是开发中非常重要的环节,对于开源项目来说更是如此,因为开源项目要面对的是来自不同水平开发者提交的代码.所以围绕开源做持续集成(Continuous Integration)变得 ...

  5. CentOS 6.3上搭建PPTP VPN

    系统版本:CentOS 6.3_x86_64 eth0:172.16.10.72(实验环境当公网IP使用) eth1:192.168.100.50 1.检测是否支持ppp模块 # cat /dev/p ...

  6. 图论:(Code Forces) Graph and String

    Graph and String time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  7. Codeforces Round #326 (Div. 1) - C. Duff in the Army 树上倍增算法

    题意:一个n个点的数, m个人住在其中的某些点上, 每个人的标号1-m, 询问u-v 路径上标号前a个人,并输出标号,a < 10. 作法, 利用倍增, ID[j][i] 表示i到i的第2^j个 ...

  8. 浅谈二维RMQ

    针对一些二维区间最值问题,用一维RMQ来解决显然是不够的.所以,要改进算法.鉴于网上没有PASCAL版的RMQ标程与解析,所以小可在这里简单的讲一下. 核心思想和一维的一样,只是在计算区间时略有不同. ...

  9. java编译期优化与执行期优化技术浅析

    java语言的"编译期"是一段不确定的过程.由于它可能指的是前端编译器把java文件转变成class字节码文件的过程,也可能指的是虚拟机后端执行期间编译器(JIT)把字节码转变成机 ...

  10. HDU4530:小Q系列故事——大笨钟

    Problem Description 饱尝情感苦恼的小Q本打算隐居一段时间,但仅仅在3月25号一天没有出现,就有很多朋友想念他,所以,他今天决定再出来一次,正式和大家做个告别. 小Q近来睡眠情况很差 ...