Java单例模式全面解析:饿汉式、懒汉式、注册式与ThreadLocal

2 下载量 114 浏览量 更新于2024-08-31 收藏 103KB PDF 举报
"这篇资源详细介绍了Java中的单例模式,包括其定义、目的以及常见的四种实现方式:饿汉式、懒汉式、注册式(容器式和枚举式)和ThreadLocal式。单例模式的主要目标是确保类只有一个实例,并提供全局访问点,常用于控制共享资源的访问。文章通过示例代码对每种实现方式进行了解析和优缺点分析。" 单例模式是一种设计模式,它限制类的实例化过程,保证在整个应用程序中,一个类只有一个实例。这种模式常用于需要频繁实例化然后销毁的对象,或者创建对象需要消耗大量资源的情况,以节省内存并提高性能。 一、饿汉式单例 饿汉式单例在类加载时就创建实例,因此是线程安全的。其优点是执行效率高,不存在线程竞争,但缺点是无论是否使用,都会预先占用内存,可能导致不必要的资源浪费。例如: ```java public class HungrySingleton { private static final HungrySingleton hungrySingleton = new HungrySingleton(); private HungrySingleton() {} public static HungrySingleton getInstance() { return hungrySingleton; } } ``` 二、懒汉式单例 懒汉式单例延迟到首次调用`getInstance()`方法时才创建实例。原始的懒汉式实现可能存在线程安全问题,因此有多种优化方案,如synchronized修饰`getInstance()`方法、双重检查锁定(DCL)和内部类实现。 1. 普通写法(非线程安全) ```java public class LazySingleton { private static LazySingleton instance; private LazySingleton() {} public static synchronized LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } } ``` 2. synchronized写法(线程安全,但效率较低) 3. DCL(Double-Check Locking)写法(线程安全且效率较高) ```java public class DclLazySingleton { private volatile static DclLazySingleton instance; private DclLazySingleton() {} public static DclLazySingleton getInstance() { if (instance == null) { synchronized (DclLazySingleton.class) { if (instance == null) { instance = new DclLazySingleton(); } } } return instance; } } ``` 4. 内部类写法(线程安全,避免同步,只在首次调用时初始化) ```java public class InnerClassSingleton { private static class SingletonHolder { private static final InnerClassSingleton INSTANCE = new InnerClassSingleton(); } private InnerClassSingleton() {} public static InnerClassSingleton getInstance() { return SingletonHolder.INSTANCE; } } ``` 三、注册式(容器式)单例 这种实现方式将单例的创建交给容器管理,例如Spring框架。在枚举中实现单例也是注册式的一种,既线程安全又避免了同步: ```java public enum EnumSingleton { INSTANCE; public void doSomething() { // ... } } ``` 四、ThreadLocal式单例 ThreadLocal为每个线程提供了一个独立的单例副本,避免了线程安全问题,但可能导致内存泄漏: ```java public class ThreadLocalSingleton { private static final ThreadLocal<ThreadLocalSingleton> instance = new ThreadLocal<>(); private ThreadLocalSingleton() {} public static ThreadLocalSingleton getInstance() { ThreadLocalSingleton localInstance = instance.get(); if (localInstance == null) { instance.set(new ThreadLocalSingleton()); } return localInstance; } } ``` 每种单例模式都有其适用场景,开发者应根据实际需求选择合适的实现方式。