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. BZOJ 1027 合金

    Description 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的 ...

  2. A Statistical View of Deep Learning (III): Memory and Kernels

    A Statistical View of Deep Learning (III): Memory and Kernels Memory, the ways in which we remember ...

  3. 利用CSP探测网站登陆状态

    0x00 背景 今天看到zone里有同学发帖说了探测支付宝登录状态的帖子:http://zone.wooyun.org/content/17665 由此我想到了我们parsec的@/fd 半年前提到的 ...

  4. c# 基础连接已经关闭: 连接被意外关闭,错误的解决

    原文:c# 基础连接已经关闭: 连接被意外关闭,错误的解决 调试一个使用HttpWebRequest模拟提交表单的程序的时候频繁出现上述错误提示,google了一下发现了几个解决方案.1.在appli ...

  5. DB_WRITER_PROCESSES与LOG_ARCHIVE_MAX_PROCESSES

    DB_WRITER_PROCESSES Property  Description Parameter type  Integer Default value  1 or CPU_COUNT / 8, ...

  6. centos 6.5关闭NetworkManager

    jrhmpt01:/root# rpm -qa | grep -i network NetworkManager-glib-0.8.1-99.el6.x86_64 system-config-netw ...

  7. [LeetCode#136, 137]Single Number, Single Number 2

    The question: Single Number Given an array of integers, every element appears twice except for one. ...

  8. vim学习与理解

    1. 转变思维 --> vim 无鼠标文本编辑工具 在鸟哥的linux私房菜中,是这么说明linux的: 1. vim是linux like系统中非常强大的一个文本编辑工具,历史悠久,很多系统都 ...

  9. HDU 2476 String painter(记忆化搜索, DP)

    题目大意: 给你两个串,有一个操作! 操作时可以把某个区间(L,R) 之间的所有字符变成同一个字符.现在给你两个串A,B要求最少的步骤把A串变成B串. 题目分析: 区间DP, 假如我们直接想把A变成B ...

  10. 图论(网络流,二分图最小点权覆盖):POJ 2125 Destroying The Graph

    Destroying The Graph   Description Alice and Bob play the following game. First, Alice draws some di ...