Java 单例模式详解

目录

[1. 饿汉式(Eager Initialization)](#1. 饿汉式(Eager Initialization))

[2. 懒汉式(Lazy Initialization)](#2. 懒汉式(Lazy Initialization))

[3. 懒汉式 + 同步锁(线程安全)](#3. 懒汉式 + 同步锁(线程安全))

[4. 双重检查锁(Double-Checked Locking)](#4. 双重检查锁(Double-Checked Locking))

[5. 静态内部类(推荐)](#5. 静态内部类(推荐))

[6. 枚举(最佳实践)](#6. 枚举(最佳实践))

单例模式的序列化与反序列化问题

单例模式适用场景

总结


单例模式是 Java 中最简单且最常用的设计模式之一,其核心思想是确保一个类只有一个实例,并提供全局访问点。下面分别详解 Java 中的单例模式:

1. 饿汉式(Eager Initialization)

特点 :类加载时立即创建实例,线程安全。
缺点:不支持延迟加载,可能造成资源浪费。

java 复制代码
public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
    
    private Singleton() {} // 私有构造函数
    
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

2. 懒汉式(Lazy Initialization)

特点 :首次调用时创建实例,支持延迟加载。
缺点:多线程环境下不安全。

java 复制代码
public class Singleton {
    private static Singleton INSTANCE;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (INSTANCE == null) { // 多线程可能同时进入此判断
            INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}

3. 懒汉式 + 同步锁(线程安全)

特点 :通过synchronized保证线程安全。
缺点:每次调用都加锁,性能开销大。

Dart 复制代码
public class Singleton {
    private static Singleton INSTANCE;
    
    private Singleton() {}
    
    public static synchronized Singleton getInstance() { // 方法级同步
        if (INSTANCE == null) {
            INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}

4. 双重检查锁(Double-Checked Locking)

特点 :线程安全且性能优化,仅首次创建时加锁。
关键点 :使用volatile关键字禁止指令重排序。

Dart 复制代码
public class Singleton {
    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;
    }
}

5. 静态内部类(推荐)

特点 :线程安全、支持延迟加载,实现简洁。
原理:JVM 保证静态内部类的初始化线程安全。

Dart 复制代码
public class Singleton {
    private Singleton() {}
    
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

6. 枚举(最佳实践)

特点 :线程安全、自动支持序列化机制、防止反射攻击。
推荐场景:需要绝对防止单例被破坏的场景。

Dart 复制代码
public enum Singleton {
    INSTANCE;
    
    // 可以添加方法
    public void doSomething() {
        System.out.println("Singleton method called");
    }
}

单例模式的序列化与反序列化问题

如果单例类实现了Serializable接口,需添加readResolve()方法防止反序列化时创建新实例:

Dart 复制代码
private Object readResolve() {
    return INSTANCE;
}

单例模式适用场景

  • 资源管理器(如数据库连接池、线程池)。
  • 配置文件管理。
  • 日志记录器。
  • GUI 中的窗口管理器。

总结

推荐使用静态内部类 或枚举实现单例模式:

  • 静态内部类:简洁、安全、支持延迟加载。
  • 枚举:防反射、防序列化攻击,写法优雅。

避免使用普通懒汉式 ,在多线程环境下需使用双重检查锁或更优方案

相关推荐
liyi_hz20084 分钟前
O2OA(翱途) V10.1 即将发布|功能再升级,安全再加固,协同更高效!
java·javascript·windows·开源软件
骑着蜗牛撵大象3277 分钟前
AI Agent 工程化开发实战(三):用 StateGraph 给智能体搭一条可回放的状态流水线
java·开发语言·jvm·ai·状态管理·langgraph·stategraph
itmigrate22 分钟前
Rust 里的所有权误区:不是不写 clone 就叫高性能
开发语言·后端·rust
Brilliantwxx28 分钟前
【Linux】 文件访问与路径解析:目录、文件名、dentry、路径缓冲与 dcache 全解析
linux·运维·服务器·开发语言·spring
鬼手点金44 分钟前
KV Cache 未必是一次性的:可编辑、可组合的“笔记”
java·人工智能·笔记·学习·自动化·1024程序员节
摇滚侠1 小时前
《On Java 中文版 基础卷》阅读笔记 初始化和清理 08
java·开发语言·笔记
xiangyun611 小时前
C++ 手撕 shared_ptr:引用计数与控制块到底长什么样?
开发语言·c++·算法·面试·stl
海鸥-w1 小时前
Redis 配置与排错说明
java·数据库·redis·bootstrap
XiYang-DING1 小时前
P4009.和为K的子数组个数 & P5522.异或和为 k 的子数组个数
java·开发语言
TinyKey1 小时前
malloc_debug_notes
java