Design Pattern —— Singleton
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的更多相关文章
- [Design Pattern] Singleton Pattern 简单案例
Singleton Pattern, 即单例模式,用于获取类的一个对象,该对象在整个应用中是其类的唯一对象.单例模式属于创建类的设计模式. SingleObject 作为单例类,内含了一个静态私有的 ...
- (Design Pattern) Singleton.
Role: The purpose of the Singleton pattern is to ensure that there is only one instance of a class, ...
- Design Pattern Singleton 单一模式
单一模式的几个注意点: 一) 设计单一模式,首先须要把构造函数给私有化了,不让外界訪问,那么外界仅仅能通过提供的函数获取一个新的类. 二) C++的单一模式,记得要在类外初始化一个类,否则或内存出错的 ...
- python singleton design pattern super() 多继承
python singleton design pattern decorate baseclass metaclass import module super() 一.A decorator de ...
- 说说设计模式~大话目录(Design Pattern)
回到占占推荐博客索引 设计模式(Design pattern)与其它知识不同,它没有华丽的外表,没有吸引人的工具去实现,它是一种心法,一种内功,如果你希望在软件开发领域有一种新的突破,一个质的飞越,那 ...
- 设计模式(Design Pattern)系列之.NET专题
最近,不是特别忙,重新翻了下设计模式,特地在此记录一下.会不定期更新本系列专题文章. 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用 ...
- [转]Design Pattern Interview Questions - Part 4
Bridge Pattern, Composite Pattern, Decorator Pattern, Facade Pattern, COR Pattern, Proxy Pattern, te ...
- [转]Design Pattern Interview Questions - Part 1
Factory, Abstract factory, prototype pattern (B) What are design patterns? (A) Can you explain facto ...
- Null Object Design Pattern (Python recipe)
Null Object 个人感觉非常有用.也是在review公司其他同事写代码的时候看到. 当时使用了flask的request全局请求变量g,然后使用了g.x保存了一个东西. 当时在view代码读取 ...
随机推荐
- mapreduce (七) 几个实例
http://hi.baidu.com/hzd2712/item/d2465ae65270ab3e4cdcaf55 MapReduce几个典型的例子 在Google的<MapReduce: Si ...
- Delphi控件的透明与不透明(要挨个解释一下原因),对InvalidateControl的关键理解
procedure TForm1.Button3Click(Sender: TObject);begin if (csOpaque in ControlStyle) then ShowMessage( ...
- Linux Shell脚本Ldd命令原理及使用方法
1.首先ldd不是一个可执行程序,而只是一个shell脚本2.ldd能够显示可执行模块的dependency,其原理是通过设置一系列的环境变量如下:LD_TRACE_LOADED_OBJECTS.LD ...
- github Travis CI 持续集成
一个项目如何保证代码质量是开发中非常重要的环节,对于开源项目来说更是如此,因为开源项目要面对的是来自不同水平开发者提交的代码.所以围绕开源做持续集成(Continuous Integration)变得 ...
- 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 ...
- 图论:(Code Forces) Graph and String
Graph and String time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- 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个 ...
- 浅谈二维RMQ
针对一些二维区间最值问题,用一维RMQ来解决显然是不够的.所以,要改进算法.鉴于网上没有PASCAL版的RMQ标程与解析,所以小可在这里简单的讲一下. 核心思想和一维的一样,只是在计算区间时略有不同. ...
- java编译期优化与执行期优化技术浅析
java语言的"编译期"是一段不确定的过程.由于它可能指的是前端编译器把java文件转变成class字节码文件的过程,也可能指的是虚拟机后端执行期间编译器(JIT)把字节码转变成机 ...
- HDU4530:小Q系列故事——大笨钟
Problem Description 饱尝情感苦恼的小Q本打算隐居一段时间,但仅仅在3月25号一天没有出现,就有很多朋友想念他,所以,他今天决定再出来一次,正式和大家做个告别. 小Q近来睡眠情况很差 ...