参考:http://www.runoob.com/design-pattern/singleton-pattern.html
代码仓库:https://github.com/jianghan0712/design-pattern
一、综述
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,也是相当常用的创造模式之一。它能保证在对象生命周期中,只存在单个对象的存在,并对外提供一个可以访问自己的全局方法getInstance。主要解决对于一个全局使用的类,阻止它频繁的创建和销毁。
二、主要思想
几个关键点:
1、类的构造函数是private的,自身是全局的
2、当外部变量想要创建这个对象时,如果已存在实例,直接返回,如果尚未创建实例,创建后返回。
3、延迟加载(Laze load):如果这个单例对象从系统初始化起,就创建成功,则称非惰性;如果直到被初次调用时才创建,则称为惰性加载。
三、示例UML
以下示例的几种单例模式写法,基本均遵循以下UML。
四、代码示例
几种常见单例模式的写法,并不包含所有方式
1、懒汉式
(1)线程不安全(延迟加载)
线程不安全,多线程环境下,出现多个实例的情况很可能出现,不建议采用这种方式实现。
//懒汉式,线程不安全
public class Singleton_1{
private static Singleton_1 instance;
private Singleton_1() {
}
public static Singleton_1 getInstance() {
if(instance == null) {
instance = new Singleton_1();
}
return instance;
}
}
(2)线程安全(延迟加载)
synchronized 的存在,线程安全。存在性能问题,对于性能要求不高的系统可以采用。
//懒汉式,线程安全
public class Singleton_2 {
private static Singleton_2 instance;
private Singleton_2 (){}
//与第一种唯一的区别在于synchronized
public static synchronized Singleton_2 getInstance() {
if (instance == null) {
instance = new Singleton_2();
}
return instance;
}
}
2、饿汉式(线程安全,非延迟加载)
比较常见的写法,采用非延迟加载,在系统初始化时,便进行了类加载,所以能够在多线程条件下使用。 但是由于没有延迟加载,当系统中有大量的单例类时,很容易产生非常多的垃圾
//饿汉式
public class Singleton_3 {
//在类加载时就进行了初始化,所以不是延迟加载类型
private static Singleton_3 instance = new Singleton_3();
private Singleton_3() {}
public static Singleton_3 getInstance() {
return instance;
}
}
3、双检锁/双重校验锁(线程安全,延迟加载)
所谓双重检验,假设在多线程环境下,线程1在创建对象时,线程2可能也要准备创建该对象。所以线程1首先锁住类,然后再判断一次该对象是否为空,如果为空则创建,否则该对象已经在其他线程中创建过了。
public class Singleton_4 {
private volatile static Singleton_4 instance;
private Singleton_4() {}
public static Singleton_4 getInstance() {
if(instance == null) {
synchronized (Singleton_4.class) {
if(instance == null) {
instance = new Singleton_4();
}
}
}
return instance;
}
}
4、静态内部类
这种写法有点类似饿汉式,但因为采用静态内部类,根据加载机制,只有因为外部类在初始化时没有被加载,所以内部类不会被加载,只有getInstance被调用时,才会加载内部类,达到了延迟加载的效果
public class Singleton_5 {
//静态内部类
private static class SingletonHodler{
private static final Singleton_5 INSTANCE = new Singleton_5();
}
private Singleton_5() {}
public static final Singleton_5 getInstance() {
return SingletonHodler.INSTANCE;
}
}
5、枚举法
public enum Singleton_6 {
INSTANCE;
public void whateverMethod() {
}
}
//调用时,使用Singleton_6.INSTANCE
五、总结
名称 | 是否线程安全 | 是否支持惰性加载 | 实现复杂度 |
懒汉式(1) | 否 | 是 | 简单 |
懒汉式(2) | 是 | 是 | 简单 |
饿汉式 | 是 | 否 | 简单 |
双重加锁 | 是 | 是 | 复杂 |
内部静态类 | 是 | 是 | 一般 |
枚举 | 是 | 否 | 简单 |