创建型-单例模式

饿汉式

1
2
3
4
5
6
7
8
9
10
11
public class Singleton {
private static final Singleton instance = new Singleton(); //用于引用全局唯一的单例对象,在一开始就创建好

private Singleton() { //不允许随便new
}

public static Singleton getInstance() { //获取全局唯一的单例对象
return instance;
}

}
1
2
3
4
5
6
public class Main {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
System.out.println(instance);
}
}

懒汉式

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

private static Singleton instance; //在一开始不创建对象

private Singleton() {
}

public static Singleton getInstance() {
if (instance == null) { //如果实例为空就创建
instance = new Singleton();
}
return instance;
}
}

但是这种方法有种缺陷,由于懒汉式在方法中进行初始化,在多线程的环境下,可能会出现问题。

懒汉式-改进

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

private static Singleton instance;

private Singleton() {
}

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

但是这种效率比较低,只能又一个线程能进入同步块,其他的必须要等待

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

private static volatile Singleton instance;

private Singleton() {
}

public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton(); //双重检查
}
}
}
return instance;
}
}

双重检查可以确保在多线程环境下也能保持单例的唯一性,同时尽可能地减少了同步的开销。

JAVA特有的写法

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

private Singleton() {
}
private static class SingletonHolder { //由静态内部类持有单例对象,根据类加载的特性,仅使用Singleton类时,不会对静态内部类进行初始化
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() { //只有真正使用内部类时,才会进行类初始化
return SingletonHolder.INSTANCE;
}

}

在Java中,静态内部类在被使用之前是不会被初始化的,这是由类加载器的工作原理决定的。

当程序第一次访问静态内部类 SingletonHolder 时,JVM 会加载 SingletonHolder 类。这个加载过程是延迟的,只有在真正需要使用 SingletonHolder 类时才会触发。所以,即使 Singleton 类被加载了,但是不会导致 SingletonHolder 类被加载,也就不会创建单例对象。


创建型-单例模式
https://sp4rks3.github.io/2024/05/10/JAVA设计模式/单例模式/
作者
Sp4rks3
发布于
2024年5月10日
许可协议