单例

博客介绍了Java单例模式不同实现方式的线程安全性。包括普通饿汉模式、普通懒汉模式、加synchronized的懒汉模式、双重校验锁、加volatile的双重校验锁、静态内部类和枚举等方式,其中部分方式线程安全,部分非线程安全,枚举方式为推荐写法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

普通饿汉模式 – 线程安全

	public class Out {
	    /**
	     * 加载类的时候就会执行(只执行一次)
	     * 会增加服务启动负担
	     */
	    private static Out out = new Out();
	    public static Out getInstance() {
	        return out;
	    }
	}

普通懒汉模式 – 非线程安全

	public class Out {
	    private static Out out = null;
	    /**
	     * 该方法在并发时,会导致生成的对象被其他线程覆盖的问题
	     */
	    public static Out getInstance() {
	        if (out == null) {
	            out = new Out();
	        }
	        return out;
	    }
	}

加synchronized的懒汉模式 – 线程安全

    public class Out {
        private static Out out = null;
        /**
         * 方法加锁,线程安全
         * 并发效率低
         */
        public static synchronized Out getInstance() {
            if (out == null) {
                out = new Out();
            }
            return out;
        }
    }

双重校验锁 – 非线程安全

	public static class Out {
	    private static Out out = null;
	    public static Out getInstance() {
	        /**
	         * 第一层判空会因为指令重排,导致判断实例不为空,从而返回一个没有初始化完成的实例给线程
	         */
	        if (out == null) {
	            synchronized (Out.class) {
	                if (out == null) {
	                    /**
	                     * 指令重排机制会打乱下面的执行顺序
	                     * memory = allocate(); //1.分配对象内存空间
	                     * instance(memory);    //2.初始化对象
	                     * instance = memory;   //3.设置instance指向刚分配的内存地址,此时instance!=null
	                     */
	                    out = new Out();
	                }
	            }
	        }
	        return out;
	    }
	}

加volatile的双重校验锁 – 线程安全

	public static class Out {
	    private static volatile Out out = null;
	    public static Out getInstance() {
	        /**
	         * volatile禁止实例初始化过程的指令重排
	         */
	        if (out == null) {
	            synchronized (Out.class) {
	                if (out == null) {
	                    out = new Out();
	                }
	            }
	        }
	        return out;
	    }
	}

静态内部类 – 线程安全(反序列化会生成新的实例)

     public class Out {
        /**
         * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
         * 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
         */
        private static class Singleton{
            /**
             * 静态初始化器,由JVM来保证线程安全
             */
            private static Out out = new Out();
        }
        public static Out getInstance(){
            return Singleton.out;
        }
    }

枚举 – 线程安全(推荐写法)

    public class Out {
        /**
        * 由JVM保证懒加载和线程安全(只有在调用的时候,才会生成单例,并且只会执行一次)
        *
        * 防止反序列化生成新对象(反射在通过newInstance创建对象时,会检查该类是否ENUM修饰,如果是则抛出异常,反射失败)
        */
        public enum Singleton {
            Singleton;
            private static Out out = new Out();
            }
        public static Out getInstance() {
        	return Singleton.out;
        }
    }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发财猪猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值