java实现单例模式

  1. 饿汉式(Eager Initialization):在类加载时就创建实例,线程安全,但可能会造成资源浪费。

    public class Singleton {
        private static final Singleton instance = new Singleton();
        private Singleton() {}
        public static Singleton getInstance() {
            return instance;
        }
    }
    
  2. 懒汉式(Lazy Initialization):在第一次调用获取实例方法时才创建实例,可能存在线程安全问题。

    public class Singleton {
        private static Singleton instance;
        private Singleton() {}
        public static Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    
  3. 双重检查锁(Double-Checked Locking):在懒汉式基础上加入双重检查锁,解决线程安全问题,避免每次获取实例都加锁静态内部类(Static Inner Class)
    /**
     * 双重检测锁实现单例模式(使用volatile):解决指令重排可能带来的问题
     * volatile只保证可见性、有序性、禁止指令重排序、不保证原子性
     * 1.可见性(Visibility):
     *      当一个变量被声明为 volatile 后,线程在读取这个变量的值时,会直接从主内存中读取,而不是从线程的工作内存中读取。
     *      任何对该变量的修改都会立即被其他线程所看到,从而确保了变量的可见性。
     *
     * 2.禁止指令重排序(Prevents Reordering):
     *      volatile 关键字还可以防止编译器对代码的优化,以避免指令重排序。这样可以确保代码的执行顺序符合程序员的预期。
     *
     * 3.不保证原子性(Not Atomic):
     *      volatile 关键字能够保证变量的可见性和禁止指令重排序,但并不能保证操作的原子性。对于涉及多步操作的情况,
     *      volatile 不能替代 synchronized。
     *
     * 4.适用场景:
     *      volatile 适用于状态标志、双重检查锁定(Double-Checked Locking)、单例模式等场景,其中需要保证变量的可见性,但不需要原子性。
     *
     * 5.内存语义:
     *      当一个变量被声明为 volatile 后,对这个变量的读写操作将具有内存语义,即对该变量的操作不会被重排序,保证了多线程环境下的线程安全性。
     *
     */
    public class Singleton {
    
        private Singleton() {
        }
    
        private static volatile Singleton instance = null;
    
        public static Singleton getInstance(){
            if (instance == null) {
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
  4. 静态内部类(Static Inner Class):利用静态内部类的特性实现延迟加载和线程安全。
    public class Singleton {
        private Singleton() {}
        public static Singleton getInstance() {
            return SingletonHolder.INSTANCE;
        }
        private static class SingletonHolder {
            private static final Singleton INSTANCE = new Singleton();
        }
    }
  5. 枚举(Enum):利用枚举的特性实现单例,天然线程安全,防止反射和序列化问题。

    public enum Singleton {
        INSTANCE;
        // 可以添加其他方法或属性
    }

     6.防止反射打破单例:在单例类的构造函数中添加逻辑,以防止反射攻击并确保单例只被 创建一次:

private Singleton() {
    if (instance != null) {
        throw new RuntimeException("Singleton instance already exists. Use getInstance() method to get the instance.");
    }
}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值