单例模式(Singleton Pattern)

2024/3/27 Java进阶

# 1、单例模式核心

一个类只能实例化一次,保证每次返回都是同一个实例对象。

  • 私有化构造方法使得该类无法在外部通过new进行实例化
  • 将类对象设置为static类型
  • 饿汉模式加volatile防止重排序
  • 加锁保证线程安全

# 2、实现方式

# 2.1、饿汉模式-线程安全

public class SingLetonMode {

    // 静态对象
    private static SingLetonMode singLetonMode = new SingLetonMode();

    // 私有化构造方法使得该类无法在外部通过new进行实例化
    private SingLetonMode() {}

    // 饿汉模式,通过synchronized保证线程安全,并且初始化后就创建了
    public static synchronized SingLetonMode getInstance(){
        return singLetonMode;
    }

    // 对象实例方法
    private void getName(){
        System.out.println("饿汉模式");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 2.2、懒汉模式-线程不安全

public class SingLetonMode {

    // 静态变量,volatile防止重排序
    private static volatile SingLetonMode singLetonMode;

    // 私有化构造方法使得该类无法在外部通过new进行实例化
    private SingLetonMode() {}

    // 懒汉模式,线程不安全
    public static SingLetonMode getInstance(){
       if(singLetonMode==null){
           singLetonMode = new SingLetonMode();
       }
       return singLetonMode;
    }

    // 对象实例方法
    public void getName(){
        System.out.println("懒汉模式");
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 2.3、懒汉模式-synchronized保证线程安全

public class SingLetonMode {

    // 静态变量,volatile防止重排序
    private static volatile  SingLetonMode singLetonMode;

    // 私有化构造方法使得该类无法在外部通过new进行实例化
    private SingLetonMode() {}

    // 懒汉模式,通过synchronized保证线程安全,但是效率慢
    public static synchronized SingLetonMode getInstance(){
        if(singLetonMode==null){
            singLetonMode = new SingLetonMode();
        }
        return singLetonMode;
    }

    // 对象实例方法
    private void getName(){
        System.out.println("懒汉模式");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 2.4、懒汉模式-双重检查锁保证线程安全

public class SingLetonMode {

    // 静态变量,volatile防止重排序
    private static volatile  SingLetonMode singLetonMode;

    // 私有化构造方法使得该类无法在外部通过new进行实例化
    private SingLetonMode() {}

    // 懒汉模式,通过双重检查锁保证线程安全,并保证效率(锁粒度小)
    public static SingLetonMode getInstance(){
        if (singLetonMode==null){
            synchronized (SingLetonMode.class){
                if(singLetonMode==null){
                    singLetonMode = new SingLetonMode();
                }
            }
        }
        return singLetonMode;
    }

    // 对象实例方法
    private void getName(){
        System.out.println("懒汉模式");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 2.5、懒汉模式-静态内部类方式

public class SingLetonMode {

    private SingLetonMode() {}

    // 当 SingLetonMode 类加载时,静态内部类 Singleton 没有被加载进内存,调用getInstance时才加载
    private static class Singleton{
        // 虚拟机提供了对线程安全的支持
        private static final SingLetonMode singleton = new SingLetonMode();
    }

    // 初始化时,不进行调用,首次调用才初始化 Singleton.singleton
    public static SingLetonMode getInstance(){
        return Singleton.singleton;
    }

    // 对象实例方法
    private void getName(){
        System.out.println("懒汉模式");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 2.6、枚举单例

能够防止反射攻击,具体可以看:枚举详解

public enum  SingletonEnum {
    INSTANCE;

    private String name;

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13