单例模式还能这样写?
单例模式,也叫单子模式,是一种常用的软件设计模式,属于创建型模式的一种。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。

# 饿汉式单例
所谓的“饿汉式”就是在类加载时就完成了单例对象的初始化。这会延长类加载的时间,但在获取对象方面具有优势。基于类加载的方式虽然能够避免多线程的同步问题,但也不能保证会有另外的因素导致类再次装载。示例代码:
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 懒汉式单例
所谓的“懒汉式”就是在需要使用单例对象时才将器创建出来,这样能达到延迟加载的目的。在单线程环境下,饿汉式单例模式是最常用的单例模式。
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if(instance == null) instance = new Singleton();
return instance;
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
考虑多线程安全,给getInstance()添加关键字synchronized得到懒汉式单例的线程安全版本:
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static synchronized Singleton getInstance() {
if(instance == null) instance = new Singleton();
return instance;
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
盲目的给方法添加上synchronized对性能损耗非常大,必须缩小synchronized的范围。
# 双重锁检查模式 (DCL)
双重锁检查模式单例对象是延迟初始化并且是线程安全的。这种方式采用双重检查机制,安全且在多线程情况下能保持高性能。DCL顾名思义,它进行了两次的判断,第一次是为了避免不要的实例,第二次是为了进行同步,避免多线程问题。JVM中可能会进行对创建singleton = new Singleton()对象进行指令重排序,导致出现多个实例,因而在多线程访问下存在风险,使用volatile修饰signleton实例变量有效,解决该问题。
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;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 静态内部类
利用静态内部类的特性,能够同时兼顾线程安全和延迟加载却不需要对方法或代码块进行加锁。
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
提示
静态内部类: 类加载时不加载静态内部类,只有在使用时才会进行初始化。
# 枚举
利用枚举的特性,让JVM来帮我们保证线程安全和单一实例的问题。除此之外,写法还特别简单。
public class Singleton {
private Singleton(){}
private static enum SingletonHolder{
INSTANCE;
private Singleton instance;
private SingletonHolder(){
instance = new Singleton();
}
public Singleton getInstnce(){
return instance;
}
}
public static Singleton getInstance(){
return SingletonHolder.INSTANCE.getInstnce();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
上次更新: 2020/09/02, 15:09:00