Java案例如何实现单例模式?

wen python案例 2

本文目录导读:

Java案例如何实现单例模式?

  1. 饿汉式(线程安全,加载时就创建)
  2. 懒汉式(线程不安全)
  3. 懒汉式(线程安全,同步方法)
  4. 双重检查锁定(DCL,推荐方式)
  5. 静态内部类(推荐方式)
  6. 枚举方式(最安全,Effective Java推荐)
  7. 完整示例:数据库连接池管理器
  8. 测试代码
  9. 总结:如何选择?

我来为你详细介绍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) 延迟加载、最小化同步开销
最安全 枚举 防反射、防序列化破坏
简单场景 饿汉式 实现最简单

建议

  1. 一般项目:使用静态内部类方式
  2. 高性能要求:使用DCL方式
  3. 涉及序列化:使用枚举方式
  4. 避免使用:懒汉式(同步方法)和线程不安全的懒汉式

这样的实现既保证了单例的唯一性,又兼顾了性能和安全性。

抱歉,评论功能暂时关闭!