单利模式(线性安全)

public class Singleton {
	
	private static class SingletonHolder {
		private static Singleton instance = new Singleton();
	}

	private Singleton() {
	}

	public static Singleton getInstance() {
		return SingletonHolder.instance;
	}

}

优点:
1、使用类的静态内部类实现的单例模式,既保证了线程安全有保证了懒加载,同时不会因为加锁的方式耗费性能。
2、这主要是因为JVM虚拟机可以保证多线程并发访问的正确性,也就是一个类的构造方法在多线程环境下可以被正确的加载。

### 单例模式下的线程安全实现 #### 方法一:饿汉式 饿汉式是一种最简单的单例模式实现方式,它通过在类加载时初始化实例来确保线程安全性。由于实例是在类加载阶段完成的,因此即使在多线程环境下也不会出现问题。 ```java public class Singleton { // 静态变量,在类加载时被初始化 private static final Singleton INSTANCE = new Singleton(); // 私有构造函数防止外部实例化 private Singleton() {} // 提供全局访问点 public static Singleton getInstance() { return INSTANCE; } } ``` 这种方式的优点在于简单易懂且天然支持线程安全[^1]。然而它的缺点是无论是否需要使用该实例都会提前创建,可能导致不必要的内存占用。 --- #### 方法二:双重检查锁定(Double-Checked Locking) 双重检查锁定是一种延迟加载的方式,既保证了线程安全又避免了每次调用 `getInstance` 时都进行同步操作,从而提高了性能。 ```java public class Singleton { // 使用 volatile 关键字防止指令重排序 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` 的作用,它可以阻止 JVM 和 CPU 对于新对象的指令重排序[^3]。如果没有 `volatile`,可能会导致某些线程读取到未完全初始化的对象。 --- #### 方法三:静态内部类 利用 Java 的类加载机制,可以通过静态内部类的方式来实现线程安全的懒加载单例模式。 ```java public class Singleton { // 私有构造函数防止外部实例化 private Singleton() {} // 定义一个静态内部类 private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } // 提供全局访问点 public static Singleton getInstance() { return SingletonHolder.INSTANCE; } } ``` 当首次调用 `getInstance()` 方法时,才会触发 `SingletonHolder` 类的加载并初始化其成员变量 `INSTANCE`。这种实现方式不仅实现了懒加载,还无需显式的同步代码,因而具有较高的效率[^2]。 --- #### 方法四:枚举类型 枚举类型的单例模式是最简洁的一种实现方式,同时也能很好地解决序列化和反射攻击带来的问题。 ```java public enum Singleton { INSTANCE; // 可以在此处定义其他方法或属性 public void doSomething() { System.out.println("Doing something..."); } } // 调用方式 Singleton.INSTANCE.doSomething(); ``` 这种方法的优势在于 JDK 自身会保证枚举类型的线程安全性,并且能够抵御反序列化产生的新的实例[^4]。 --- #### 方法五:基于容器的单例管理 如果项目中有 Spring 或 Guice 这样的依赖注入框架,则可以直接让框架负责单例的管理和生命周期控制。 ```java @Component @Scope("singleton") // 如果使用 XML 配置则设置 scope="singleton" public class SingletonBean { public void performAction() { System.out.println("Performing action in a singleton bean."); } } ``` 在这种情况下,Spring 框架会在应用启动时自动创建好单例 Bean 并缓存起来,后续请求均返回同一个实例[^5]。 --- ### 总结 以上介绍了几种常见的单例模式线程安全实现方案,每种都有各自的优劣: | 方案 | 是否懒加载 | 线程安全 | 缺点 | |--------------|------------|----------------|--------------------------| | 饿汉式 | 否 | 是 | 不适合资源开销较大的场景 | | 双重检查锁定 | 是 | 是 | 实现复杂度较高 | | 静态内部类 | 是 | 是 | 较难理解 | | 枚举类型 | 是 | 是 | 功能扩展有限 | 具体选择哪种方式取决于项目的实际需求以及开发者的偏好。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值