单例模式的实现方式(饿汉、懒汉、DLC、枚举)


文章参考于:

饿汉式

public class Singleton_hungry {
	/*
	 * 饿汉式:一上来就初始化对象,线程安全, 容易产生垃圾对象,类加载是就初始化,浪费内存
	 */
	private static Singleton_hungry singleton = new Singleton_hungry();

	private Singleton_hungry() {
	}

	public static synchronized Singleton_hungry getInstance() {
		return singleton;
	}
}

  • 优点:没有加锁,执行效率会提高。
  • 缺点:类加载时就初始化,浪费内存。
懒汉式

public class Singleton_lazy {
	// 懒汉式:用的时候创建对象
	private static Singleton_lazy singleton;

	private Singleton_lazy() {
	}

	public static synchronized Singleton_lazy getInstance() {
		if (null == singleton) {
			singleton = new Singleton_lazy();
		}
		return singleton;
	}
}
  • 优点:第一次调用才初始化,避免内存浪费
  • 缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率
双重校验锁

public class Singleton_DCL {
	/*
	 * 采用了双锁机制,安全且在多线程情况下能保持高性能,getSingleton() 的性能对应用程序很关键
	 */
	private volatile static Singleton_DCL singleton;

	private Singleton_DCL() {
	}

	public static Singleton_DCL getSingleton() {
		if (singleton == null) {
			synchronized (Singleton_DCL.class) {
				if (singleton == null) {
					singleton = new Singleton_DCL();
				}
			}
		}
		return singleton;
	}

}

  • DCL: double-checked locking(双重锁/双重校验锁)
  • 优点:线程安全,延迟加载,效率较高
  • singleton 采用 volatile 关键字修饰也是很有必要的, singleton = new Singleton_DCL(); 这段代码其实是分
    为三步执行:
    1. 为 singleton 分配内存空间
    2. 初始化 singleton
    3. 将 singleton 指向分配的内存地址
  • 但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1->3->2。指令重排在单线程环境下不会出先问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3,此时 T2 调用getUniqueInstance() 后发现 uniqueInstance 不为空,因此返回 uniqueInstance,但此时 uniqueInstance 还未被初始化。使用 volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。
枚举

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}
  • 优点:它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。
  • 缺点:当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new,可能会给其他开发人员造成困扰,特别是看不到源码的时候。(在实际工作中,很少使用)
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值