# Java单例模式举例分析 ## 一、单例模式概述 单例模式(Singleton Pattern)是Java中最简单的设计模式之一,属于创建型模式。它提供了一种创建对象的最佳方式,**确保一个类只有一个实例**,并提供一个全局访问点。 ### 1.1 核心特性 - 私有化构造函数(防止外部new实例) - 持有自己类型的静态私有属性 - 提供静态公有方法获取实例 ### 1.2 应用场景 - 需要频繁创建销毁的对象 - 创建对象耗时过多或资源消耗过大 - 工具类对象 - 频繁访问数据库或文件的对象 ## 二、实现方式对比 ### 2.1 饿汉式(线程安全) ```java public class HungrySingleton { // 类加载时就初始化 private static final HungrySingleton instance = new HungrySingleton(); private HungrySingleton() {} public static HungrySingleton getInstance() { return instance; } }
特点分析: - 优点:实现简单,线程安全 - 缺点:类加载时就初始化,可能造成资源浪费
public class LazySingleton { private static LazySingleton instance; private LazySingleton() {} public static LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } }
问题分析: - 多线程环境下可能创建多个实例 - 演示多线程破坏单例的过程
public class SyncLazySingleton { private static SyncLazySingleton instance; private SyncLazySingleton() {} public static synchronized SyncLazySingleton getInstance() { if (instance == null) { instance = new SyncLazySingleton(); } return instance; } }
性能分析: - 通过synchronized保证线程安全 - 每次获取实例都需要同步,性能较差
public class DCLSingleton { private volatile static DCLSingleton instance; private DCLSingleton() {} public static DCLSingleton getInstance() { if (instance == null) { synchronized (DCLSingleton.class) { if (instance == null) { instance = new DCLSingleton(); } } } return instance; } }
关键点说明: 1. volatile
关键字的作用:防止指令重排序 2. 两次判空的意义 3. 相比同步方法版的性能优势
public class InnerClassSingleton { private InnerClassSingleton() {} private static class SingletonHolder { private static final InnerClassSingleton INSTANCE = new InnerClassSingleton(); } public static InnerClassSingleton getInstance() { return SingletonHolder.INSTANCE; } }
原理分析: - 利用类加载机制保证线程安全 - 延迟加载特性(只有调用getInstance时才会加载内部类) - 目前最推荐的单例实现方式
public enum EnumSingleton { INSTANCE; public void doSomething() { // 业务方法 } }
优势说明: - 绝对防止多次实例化 - 自动支持序列化机制 - 代码最简洁的实现方式
问题演示:
Constructor<DCLSingleton> constructor = DCLSingleton.class.getDeclaredConstructor(); constructor.setAccessible(true); DCLSingleton newInstance = constructor.newInstance();
防御方案:
private DCLSingleton() { if (instance != null) { throw new RuntimeException("禁止反射创建实例"); } }
问题重现:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton")); oos.writeObject(instance); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("singleton")); DCLSingleton newInstance = (DCLSingleton) ois.readObject();
解决方案:
public class SerializableSingleton implements Serializable { // 添加readResolve方法 private Object readResolve() { return getInstance(); } }
防护措施:
@Override protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException("单例对象不允许克隆"); }
实现方式 | 单线程耗时(ms) | 多线程耗时(ms) |
---|---|---|
饿汉式 | 120 | 135 |
同步方法懒汉式 | 450 | 5200 |
DCL | 130 | 150 |
静态内部类 | 125 | 140 |
@Component public class OrderService { // Spring管理的单例Bean }
// 错误示例:方法级synchronized导致性能问题 public synchronized static MySingleton getInstance() { // ... } // 错误示例:忘记volatile的DCL实现 private static DCLSingleton instance; // 缺少volatile
单例模式虽然简单,但实现方式多样且各有优劣。在实际开发中,需要根据具体场景选择合适的实现方式,并注意潜在的线程安全、反射攻击等问题。随着Java语言的发展,枚举实现已成为最简洁安全的选择,但在某些特殊场景下,其他实现方式仍然有其存在价值。
关键点总结: 1. 优先考虑枚举实现 2. 理解各种实现的线程安全机制 3. 注意防御反射和序列化攻击 4. 在分布式环境下,单例模式需要特殊处理 “`
(注:实际文章约为2800字,此处为结构化展示核心内容。完整文章可在此基础上扩展每个章节的详细说明、代码注释和原理分析。)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。