本文目录导读:

- 饿汉式(线程安全,加载时就创建)
- 懒汉式(线程不安全)
- 懒汉式(线程安全,同步方法)
- 双重检查锁定(DCL,推荐方式)
- 静态内部类(推荐方式)
- 枚举方式(最安全,Effective Java推荐)
- 完整示例:数据库连接池管理器
- 测试代码
- 总结:如何选择?
我来为你详细介绍Java中实现单例模式的几种常见方法,从基础到高级逐步说明。
饿汉式(线程安全,加载时就创建)
public class SingletonEager {
// 类加载时就创建实例
private static final SingletonEager instance = new SingletonEager();
// 私有构造方法
private SingletonEager() {}
// 提供全局访问点
public static SingletonEager getInstance() {
return instance;
}
}
优点:实现简单,线程安全(类加载机制保证) 缺点:类加载时就创建,可能造成资源浪费
懒汉式(线程不安全)
public class SingletonLazyUnsafe {
private static SingletonLazyUnsafe instance;
private SingletonLazyUnsafe() {}
public static SingletonLazyUnsafe getInstance() {
if (instance == null) {
instance = new SingletonLazyUnsafe();
}
return instance;
}
}
问题:多线程环境下可能创建多个实例
懒汉式(线程安全,同步方法)
public class SingletonLazySafe {
private static SingletonLazySafe instance;
private SingletonLazySafe() {}
// 使用synchronized保证线程安全
public static synchronized SingletonLazySafe getInstance() {
if (instance == null) {
instance = new SingletonLazySafe();
}
return instance;
}
}
缺点:每次调用都加锁,性能较差
双重检查锁定(DCL,推荐方式)
public class SingletonDCL {
// volatile关键字防止指令重排序
private static volatile SingletonDCL instance;
private SingletonDCL() {}
public static SingletonDCL getInstance() {
if (instance == null) {
synchronized (SingletonDCL.class) {
if (instance == null) {
instance = new SingletonDCL();
}
}
}
return instance;
}
}
关键点:
volatile:防止instance = new SingletonDCL()的指令重排序- 双重检查:减少锁的开销
- 实际开发中最推荐的方式之一
静态内部类(推荐方式)
public class SingletonStaticInner {
private SingletonStaticInner() {}
// 静态内部类
private static class SingletonHolder {
private static final SingletonStaticInner INSTANCE = new SingletonStaticInner();
}
public static SingletonStaticInner getInstance() {
return SingletonHolder.INSTANCE;
}
}
优点:
- 延迟加载(只有在getInstance调用时才加载内部类)
- 线程安全(类加载机制保证)
- 性能好
枚举方式(最安全,Effective Java推荐)
public enum SingletonEnum {
INSTANCE;
// 可以添加其他方法
public void doSomething() {
System.out.println("Singleton do something");
}
}
优点:
- 简单、安全
- 自动支持序列化
- 防止反射攻击
- 绝对防止多次实例化
完整示例:数据库连接池管理器
public class DatabaseConnectionPool {
// 使用双重检查锁定
private static volatile DatabaseConnectionPool instance;
private List<Connection> connections = new ArrayList<>();
private final int MAX_CONNECTIONS = 10;
private DatabaseConnectionPool() {
initializePool();
}
private void initializePool() {
for (int i = 0; i < MAX_CONNECTIONS; i++) {
// 模拟创建数据库连接
connections.add(createConnection());
}
}
private Connection createConnection() {
// 实际项目中连接数据库
System.out.println("创建数据库连接");
return null; // 简化示例
}
public static DatabaseConnectionPool getInstance() {
if (instance == null) {
synchronized (DatabaseConnectionPool.class) {
if (instance == null) {
instance = new DatabaseConnectionPool();
}
}
}
return instance;
}
public Connection getConnection() {
if (connections.isEmpty()) {
return null;
}
return connections.remove(0);
}
public void releaseConnection(Connection conn) {
connections.add(conn);
}
}
测试代码
public class SingletonTest {
public static void main(String[] args) {
// 测试各种单例模式
testBasicSingletons();
testEnumSingleton();
testMultiThreadSafety();
}
private static void testBasicSingletons() {
SingletonDCL s1 = SingletonDCL.getInstance();
SingletonDCL s2 = SingletonDCL.getInstance();
System.out.println("DCL模式: " + (s1 == s2)); // true
SingletonStaticInner s3 = SingletonStaticInner.getInstance();
SingletonStaticInner s4 = SingletonStaticInner.getInstance();
System.out.println("静态内部类: " + (s3 == s4)); // true
SingletonEnum s5 = SingletonEnum.INSTANCE;
SingletonEnum s6 = SingletonEnum.INSTANCE;
System.out.println("枚举模式: " + (s5 == s6)); // true
}
private static void testEnumSingleton() {
SingletonEnum.INSTANCE.doSomething();
}
private static void testMultiThreadSafety() {
// 多线程测试
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
executor.execute(() -> {
SingletonDCL instance = SingletonDCL.getInstance();
System.out.println(Thread.currentThread().getName() + ": " + instance.hashCode());
});
}
executor.shutdown();
}
}
如何选择?
| 场景 | 推荐方式 | 理由 |
|---|---|---|
| 通用场景 | 静态内部类 | 延迟加载、线程安全、性能好 |
| 高性能要求 | 双重检查锁定(DCL) | 延迟加载、最小化同步开销 |
| 最安全 | 枚举 | 防反射、防序列化破坏 |
| 简单场景 | 饿汉式 | 实现最简单 |
建议:
- 一般项目:使用静态内部类方式
- 高性能要求:使用DCL方式
- 涉及序列化:使用枚举方式
- 避免使用:懒汉式(同步方法)和线程不安全的懒汉式
这样的实现既保证了单例的唯一性,又兼顾了性能和安全性。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播