Java SE笔记: 单例模式

  • 单例模式要领:
    1. 构造方法私有化
    2. 对外提供一个公开的静态的获取当前类型对象的方法.
    3. 提供一个当前类型的静态变量。
  • 单例模式分为两种:
    • 饿汉式单例:在类加载阶段就创建了对象。
    • 懒汉式单例:用到对象的时候才会创建对象。
  • 为了解决什么问题?
    1. 为了保证JVM中某一个类型的java对象永远只有一个。
    2. 为了节省内存的开销。
  • 缺点:单例模式的类无法被继承!

饿汉式(线程安全)

1
2
3
4
5
6
7
8
9
10
11
public class Singleton {

private static Singleton uniqueInstance = new Singleton();

private Singleton() {
}

public static Singleton getUniqueInstance() {
return uniqueInstance;
}
}

懒汉式(线程不安全,延迟加载)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton {

private static Singleton uniqueInstance;

private Singleton() {
}

public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}

懒汉式(线程安全,延迟加载)

  • 在方法上加锁,会影响性能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton {

private static Singleton uniqueInstance;

private Singleton() {
}

public static synchronized Singleton getUniqueInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}

双重校验锁(线程安全,延迟加载)

  • 只对实例化的语句加锁
  • 可能有多个线程进入外层if,所以在同步代码块里面再加一个锁防止多次实例化
  • volatile关键字禁止JVM的指令重排
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Singleton {

private volatile static Singleton uniqueInstance;

private Singleton() {
}

public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}

静态内部类实现(线程安全,延迟加载)

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Singleton {

private Singleton() {
}

private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getUniqueInstance() {
return SingletonHolder.INSTANCE;
}
}

枚举实现(最佳实现)

  • 防止反射攻击
  • 确保复杂序列化只创建一个实例
1
2
3
public enum Singleton {
uniqueInstance;
}
文章目录
  1. 1. 饿汉式(线程安全)
  2. 2. 懒汉式(线程不安全,延迟加载)
  3. 3. 懒汉式(线程安全,延迟加载)
  4. 4. 双重校验锁(线程安全,延迟加载)
  5. 5. 静态内部类实现(线程安全,延迟加载)
  6. 6. 枚举实现(最佳实现)