设计模式——单例
是什么
- 单例是创建型设计模式
- 在内存中只有一个实例化对象
- 全局只有一个访问点获取实例化对象
解决什么问题
- 对象重复创建,浪费开销
- 内存有多个相同的对象,浪费空间
实现方式分类
- 饿汉模式,类初始化完创建对象
- 懒汉模式,第一次调用时创建对象
饿汉模式实现方式
私有化构造方法
初始化私有的static final属性为实例化对象
对外暴露getInstance静态方法
代码示例
1
2
3
4
5
6
7
8
9
10class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
懒汉模式实现方式
getInstance方法加synchronized,防止多线程同时调用创建多个对象。所有获取单例实例化对象都会加锁。单例、线程安全、性能差。
1
2
3
4
5
6
7
8
9
10
11
12
13class Singleton {
private static Singleton INSTANCE = null;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}双重检查锁,只有在INSTANCE为空的时候加锁,常规获取单例不加锁,避免频繁加锁;给INSTANCE添加volatile,多线程其他线程可以获取INSTANCE最新创建情况。单例、线程安全、性能好。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class 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
12class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton() {
}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}枚举,枚举类型及枚举变量在JVM中都是唯一的,同时枚举类型在序列化和反序列化在JVM也是同一个,可以保证绝对单例。序列化单例、线程安全、性能好。
1
2
3public enum Singleton {
INSTANCE;
}
关联知识点
类加载过程,加载->验证->准备->解析->初始化,初始化会对静态变量赋值,由此可知饿汉模式类加载完成对象即创建完。
- 加载:字节码加载到内存
- 验证:验证格式
- 准备:静态变量分配内存,初始化默认值
- 解析:静态链接,符号引用转换为直接引用
- 初始化:静态变量赋值,静态方法区执行
静态内部类,静态内部类在使用的时候才会加载,类加载会初始化static变量。
线程安全,内存模型,volatile,synchronized,设计知识点略多,以后单独写。
枚举特性,枚举类型及枚举变量在JVM中都是唯一的。在序列化的时候Java将枚举对象的name属性输出到结果中,反序列化的时候通过java.lang.Enum的valueOf方法来根据名字查找枚举对象。