前言

很简单的单例模式实现,笔试的时候写错了💦💦,复习一下。

分类

饿汉模式

类创建时就初始化唯一实例

  • 优点:简单、线程安全
  • 缺点:可能耗费资源
1
2
3
4
5
6
7
8
9
10
public class HungrySingleton {
// 定义并初始化唯一实例
private static final HungrySingleton instance = new HungrySingleton();
// 私有化构造函数
private HungrySingleton() {}
// 返回示例的静态方法
public static HungrySingleton getUniqueInstance() {
return instance;
}
}

懒汉模式

第一次被调用时才创建实例

  • 优点:节省资源
  • 缺点:线程不安全
1
2
3
4
5
6
7
8
9
10
11
12
13
public class LazySingleton {
// 定义唯一实例,但是不初始化
private static LazySingleton instance;
// 私有化构造函数
private LazySingleton() {}
// 第一次调用时初始化
public static LazySingleton getUniqueInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}

双重检查锁定

在懒汉的基础上对初始化实例行为加锁

  • 优点:线程安全
  • 缺点:相对复杂
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class LockLazySingleton {
// 定义唯一示例,使用volatile关键字使其对所有线程可见
private volatile static LockLazySingleton instance;
// 私有化构造函数
private LockLazySingleton() {}
// 第一次调用时初始化,并使用对象锁保证只发生了一次初始化
public static LockLazySingleton getUniqueInstance() {
// 先拿到锁之后再去执行判断语句!
synchronized (LockLazySingleton.class) {
if (instance == null) {
instance = new LockLazySingleton();
}
}
return instance;
}

}

测试类

使用Java并发编程接口来进行测试,主要是测试双重检查锁模式。

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class SingletonTest {
public static void main(String[] args) throws InterruptedException {
System.out.println("饿汉1:" + HungrySingleton.getUniqueInstance());
System.out.println("饿汉2:" + HungrySingleton.getUniqueInstance());
System.out.println("懒汉1:" + LazySingleton.getUniqueInstance());
System.out.println("懒汉2:" + LazySingleton.getUniqueInstance());

int numberOfThreads = 100;
CountDownLatch latch = new CountDownLatch(numberOfThreads);
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
LockLazySingleton[] instances = new LockLazySingleton[numberOfThreads];

for (int i = 0; i < numberOfThreads; i++) {
// 使用一个final变量来保证当前线程使用的i不会被其他线程改变
final int index = i;
executor.execute(() -> {
try {
instances[index] = LockLazySingleton.getUniqueInstance();
} finally {
latch.countDown();
}
});
}

// 等待所有线程完成
latch.await();
executor.shutdown();

// 验证所有获取到的实例都是同一个实例
LockLazySingleton firstInstance = instances[0];
boolean allSame = true;
for (LockLazySingleton instance : instances) {
if (instance != firstInstance) {
allSame = false;
break;
}
}

if (allSame) {
System.out.println("Test passed: All instances are the same.");
} else {
System.out.println("Test failed: Instances are not the same.");
}
}
}

后记

GPT-4o好好用啊(*^3^)