本文目录导读:

我来给你详细讲解懒汉式(Lazy Initialization)单例模式,包括多种实现方式和完整代码案例。
什么是懒汉式单例?
懒汉式单例的特点是:实例在第一次被使用时才创建,而不是在类加载时就创建,这样可以延迟加载,节省资源。
基础懒汉式(线程不安全)
这是最简单的实现,但存在线程安全问题:
public class SingletonLazy {
// 私有静态实例,初始为null
private static SingletonLazy instance = null;
// 私有构造函数,防止外部实例化
private SingletonLazy() {
System.out.println("创建懒汉式单例");
}
// 公共的静态方法,用于获取实例
public static SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
// 测试方法
public void showMessage() {
System.out.println("懒汉式单例工作正常!");
}
}
线程安全的懒汉式(方法同步)
通过synchronized关键字保证线程安全,但性能较低:
public class SingletonLazySync {
private static SingletonLazySync instance = null;
private SingletonLazySync() {
System.out.println("创建线程安全的懒汉式单例");
}
// 同步方法,保证线程安全
public static synchronized SingletonLazySync getInstance() {
if (instance == null) {
instance = new SingletonLazySync();
}
return instance;
}
public void showMessage() {
System.out.println("线程安全的懒汉式单例工作正常!");
}
}
双重检查锁(推荐)
最优化的线程安全实现,既保证线程安全,又保证性能:
public class SingletonDoubleChecked {
// volatile关键字保证内存可见性和禁止指令重排序
private static volatile SingletonDoubleChecked instance = null;
private SingletonDoubleChecked() {
// 防止通过反射创建实例
if (instance != null) {
throw new RuntimeException("不允许反射创建单例!");
}
System.out.println("创建双重检查锁的单例");
}
public static SingletonDoubleChecked getInstance() {
// 第一次检查:如果实例已存在,直接返回
if (instance == null) {
// 同步代码块,只锁住创建实例的部分
synchronized (SingletonDoubleChecked.class) {
// 第二次检查:防止多个线程同时创建实例
if (instance == null) {
instance = new SingletonDoubleChecked();
}
}
}
return instance;
}
public void showMessage() {
System.out.println("双重检查锁的单例工作正常!");
}
}
静态内部类方式(最推荐)
利用JVM的类加载机制,实现最简单的线程安全懒加载:
public class SingletonStaticInner {
// 私有构造函数
private SingletonStaticInner() {
System.out.println("创建静态内部类单例");
}
// 静态内部类,在第一次使用时加载
private static class SingletonHolder {
// final保证可见性
private static final SingletonStaticInner INSTANCE = new SingletonStaticInner();
}
// 获取实例的方法
public static SingletonStaticInner getInstance() {
return SingletonHolder.INSTANCE;
}
public void showMessage() {
System.out.println("静态内部类单例工作正常!");
}
}
完整测试案例
创建一个完整的测试程序,验证各种懒汉式实现:
public class LazySingletonTest {
// 测试1:验证单例的唯一性
public static void testSingleton() {
System.out.println("=== 测试1:验证单例唯一性 ===");
SingletonLazy s1 = SingletonLazy.getInstance();
SingletonLazy s2 = SingletonLazy.getInstance();
System.out.println("s1 == s2? " + (s1 == s2)); // true
// 验证其他实现
SingletonDoubleChecked d1 = SingletonDoubleChecked.getInstance();
SingletonDoubleChecked d2 = SingletonDoubleChecked.getInstance();
System.out.println("双重检查锁: d1 == d2? " + (d1 == d2));
SingletonStaticInner i1 = SingletonStaticInner.getInstance();
SingletonStaticInner i2 = SingletonStaticInner.getInstance();
System.out.println("静态内部类: i1 == i2? " + (i1 == i2));
System.out.println();
}
// 测试2:验证懒加载特性(延迟加载)
public static void testLazyLoading() {
System.out.println("=== 测试2:验证懒加载特性 ===");
System.out.println("程序启动,但尚未调用getInstance()");
System.out.println("现在开始调用getInstance()...");
SingletonLazy instance = SingletonLazy.getInstance();
System.out.println("成功获取实例");
System.out.println();
}
// 测试3:多线程环境测试
public static void testMultiThread() {
System.out.println("=== 测试3:多线程环境测试 ===");
// 创建多个线程同时获取实例
int threadCount = 5;
Thread[] threads = new Thread[threadCount];
SingletonDoubleChecked[] instances = new SingletonDoubleChecked[threadCount];
for (int i = 0; i < threadCount; i++) {
final int index = i;
threads[i] = new Thread(() -> {
instances[index] = SingletonDoubleChecked.getInstance();
System.out.println("线程" + index + ": 获取实例成功,哈希值=" +
instances[index].hashCode());
});
}
// 启动所有线程
for (Thread t : threads) {
t.start();
}
// 等待所有线程结束
for (Thread t : threads) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 验证所有线程获取的是同一个实例
boolean isSame = true;
for (int i = 1; i < threadCount; i++) {
if (instances[i] != instances[0]) {
isSame = false;
break;
}
}
System.out.println("所有线程获取的实例是否相同? " + isSame);
System.out.println();
}
// 测试4:性能对比测试
public static void testPerformance() {
System.out.println("=== 测试4:性能对比测试 ===");
final int TEST_TIMES = 1000000;
// 测试双重检查锁
long startTime = System.currentTimeMillis();
for (int i = 0; i < TEST_TIMES; i++) {
SingletonDoubleChecked.getInstance();
}
long endTime = System.currentTimeMillis();
System.out.println("双重检查锁 " + TEST_TIMES + " 次获取耗时: "
+ (endTime - startTime) + "ms");
// 测试同步方法
startTime = System.currentTimeMillis();
for (int i = 0; i < TEST_TIMES; i++) {
SingletonLazySync.getInstance();
}
endTime = System.currentTimeMillis();
System.out.println("同步方法 " + TEST_TIMES + " 次获取耗时: "
+ (endTime - startTime) + "ms");
// 测试静态内部类
startTime = System.currentTimeMillis();
for (int i = 0; i < TEST_TIMES; i++) {
SingletonStaticInner.getInstance();
}
endTime = System.currentTimeMillis();
System.out.println("静态内部类 " + TEST_TIMES + " 次获取耗时: "
+ (endTime - startTime) + "ms");
System.out.println();
}
// 测试5:防御性测试(反射攻击防护)
public static void testReflectionAttack() {
System.out.println("=== 测试5:反射攻击防护测试 ===");
try {
// 尝试通过反射创建第二个实例
Class<?> clazz = Class.forName("SingletonDoubleChecked");
java.lang.reflect.Constructor<?> constructor =
clazz.getDeclaredConstructor();
constructor.setAccessible(true);
// 尝试创建新实例(应该失败)
SingletonDoubleChecked instance =
(SingletonDoubleChecked) constructor.newInstance();
System.out.println("警告!反射创建实例成功!");
} catch (Exception e) {
System.out.println("反射攻击被阻止:" + e.getMessage());
}
System.out.println();
}
// 主方法
public static void main(String[] args) {
System.out.println("========== 懒汉式单例模式测试 ==========\n");
testSingleton();
testLazyLoading();
testMultiThread();
testPerformance();
testReflectionAttack();
System.out.println("========== 测试完成 ==========");
}
}
饿汉式对比
为了更好理解,提供一个饿汉式对比:
public class SingletonEager {
// 类加载时就创建实例(饿汉式)
private static final SingletonEager INSTANCE = new SingletonEager();
private SingletonEager() {}
public static SingletonEager getInstance() {
return INSTANCE;
}
}
实现方式对比总结
| 实现方式 | 线程安全 | 懒加载 | 性能 | 推荐程度 |
|---|---|---|---|---|
| 基础懒汉式 | 高 | 不推荐 | ||
| 同步方法 | 低 | 不推荐 | ||
| 双重检查锁 | 高 | 推荐 | ||
| 静态内部类 | 高 | 最推荐 |
使用建议
- 开发环境:推荐使用静态内部类方式,代码最简洁,性能最好
- 有特殊需求:如果需要对实例初始化做特殊控制,使用双重检查锁方式
- 测试环境:可以使用基础的懒汉式,但不建议在生产环境使用
注意事项:
- 懒汉式适合创建开销大、可能需要延迟加载的场景
- 所有实现都要考虑线程安全问题
- 最好加上反射攻击的防护
- 如果有序列化需求,还需要添加
readResolve()方法
这就是懒汉式单例的完整实现和测试案例,希望能帮助你深入理解这个概念!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播