实现 Java 线程安全的 Singleton 模式
在 Java 开发中,实现一个线程安全的单例模式(Singleton)是非常重要的。下面我会逐步引导你实现这个目标。整个过程分为几个步骤,我们将会在每个步骤中讨论具体的代码实现以及该代码的作用。
步骤流程表
我们可以将实现过程梳理成以下流程:
| 步骤 | 描述 |
|---|---|
| 1 | 创建 Singleton 类 |
| 2 | 定义私有构造函数 |
| 3 | 创建一个静态私有实例 |
| 4 | 提供一个公共静态方法 |
| 5 | 实现线程安全 |
| 6 | 测试该 Singleton 类 |
1. 创建 Singleton 类
首先,我们需要创建一个 Singleton 类,这个类将会持有单一实例。
public class Singleton {
// 声明一个静态私有变量来保存实例
private static Singleton instance;
// 私有构造函数,禁止外部创建实例
private Singleton() {}
// 公共静态方法返回实例
public static Singleton getInstance() {
if (instance == null) { // 第一次检查
instance = new Singleton(); // 创建实例
}
return instance; // 返回实例
}
}
2. 定义私有构造函数
在上面的代码中,构造函数是私有的,意义在于禁止其他类直接创建 Singleton 对象。这是单例模式的关键步骤。
3. 创建静态私有实例
我们定义一个静态变量 instance 来存储 Singleton 的唯一实例。
4. 提供一个公共静态方法
getInstance() 方法检查是否已存在实例,如果没有,则创建一个。这是外界获取 Singleton 实例的方式。
5. 实现线程安全
为了确保在多线程环境下只创建一个实例,我们需要对 getInstance() 方法的实现进行改进。
我们可以使用双重检查锁定(Double-Checked Locking)。具体如下:
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
// 第一次检查
if (instance == null) {
synchronized (Singleton.class) { // 同步块
// 第二次检查
if (instance == null) {
instance = new Singleton(); // 创建实例
}
}
}
return instance; // 返回实例
}
}
在这个实现中:
- 我们首先检查
instance是否为null。 - 如果是
null,则进入synchronized块。 - 在
synchronized块内,我们再次检查instance是否为null。如果仍然为null,则创建实例。
6. 测试该 Singleton 类
最后,我们需要测试 Singleton 类,确保它是线程安全的。
public class SingletonTest {
public static void main(String[] args) {
Runnable task = () -> {
Singleton instance = Singleton.getInstance();
System.out.println(instance);
};
// 创建多个线程来测试 Singleton
for (int i = 0; i < 10; i++) {
new Thread(task).start();
}
}
}
在上面的 SingletonTest 类中,我们创建了多个线程来调用 getInstance() 方法并打印出实例。你会发现,无论多少线程并发访问,始终得到的是同一个实例。
类图示例
我们可以用 mermaid 语法表示相关的类图结构:
classDiagram
class Singleton {
<<Singleton>>
- static Singleton instance
- Singleton()
+ static Singleton getInstance()
}
结尾
在这篇文章中,我们介绍了如何实现一个线程安全的 Singleton 模式。通过明确的步骤和代码示例,我相信你能够独立完成这个实现。无论是应用于大型项目,还是小型练习,Singleton 模式都将是你的有效工具。继续学习和实践,你会在 Java 开发中逐渐得心应手!
















