单例模式(Singleton Pattern)是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。
Java 中实现单例模式有多种方法,每种方法各有优缺点。以下是几种常见的实现方法及其最佳实践。
饿汉式单例
饿汉式在 类加载时就创建实例,线程安全。
1
2
3
4
5
6
7
8
9
10
|
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
// 私有构造函数防止外部实例化
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
|
优点:
缺点:
懒汉式单例(线程不安全)
懒汉式在第一次需要实例时才创建,线程不安全。
1
2
3
4
5
6
7
8
9
10
11
12
|
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
|
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
|
优点:
缺点:
- 性能较低,每次调用
getInstance 都要进行同步
双重检查锁定(Double-Checked Locking)
双重检查锁定减少了同步的开销。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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;
}
}
|
优点:
- 线程安全
- 延迟加载
- 性能较高,只有第一次创建实例时同步。
缺点:
- 需要注意使用
volatile 关键字,防止指令重排
静态内部类
利用类加载机制确保线程安全,同时实现懒加载。
1
2
3
4
5
6
7
8
9
10
11
|
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
|
优点:
缺点:
枚举单例
枚举实现单例模式天生是线程安全的,并且防止反序列化导致重新创建新的对象。
1
2
3
4
5
6
7
|
public enum Singleton {
INSTANCE;
public void doSomething() {
// do something
}
}
|
优点:
缺点:
总结
在实际项目中,推荐使用静态内部类和枚举单例,因为它们既简单又安全,性能较高。具体选择哪种方式需要根据实际需求来决定。