关于单例模式饿汉模式的思考

单例模式中的饿汉模式和懒汉模式大家都应该非常熟悉了,但是从虚拟机类加载的角度来思考的时候,有些点我不是很清楚,特此记录一下。关于单例模式的几种写法,可以参考我之前发的博文(代码加注释)点击打开链接

我不清楚的点是在饿汉模式和懒汉模式的区别到底在哪里?

首先看饿汉模式

public class Singleton {	
        private Singleton() {
	}
	private static Singleton instance = new Singleton();
	public static Singleton getInstance() {
		return instance;
	}
}

网上很多关于饿汉模式的解释都是说会在类加载的时候就new这个单例对象,使用时候通过getInstance()方法将引用返回,如果不使用的话,会造成资源的浪费,而懒汉模式是在需要的时候再去new一个单例对象,不会造成资源的占用。但是,在《深入理解java虚拟机》一书中明确指出,虽然虚拟机规范对类的加载时机没有强制进行强制规定,但是对类的初始化做了明确的规定。当且只有在以下5种情况下才会对类进行初始化,也就是所说的主动引用。有哪5种呢?

1.遇到 new、getstatic、putstatic、invokestatic 这四条字节码指令时,如果类还没有进行过初始化,则需要先触发其初始化。生成这四条指令最常见的 Java 代码场景是:使用 new 关键字实例化对象时、读取或设置一个类的静态字段(static)时(被 static 修饰又被 final 修饰的,已在编译期把结果放入常量池的静态字段除外)、以及调用一个类的静态方法时

2.使用 Java.lang.refect 包的方法对类进行反射调用时,如果类还没有进行过初始化,则需要先触发其初始化。

3.当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。

4.当虚拟机启动时,用户需要指定一个要执行的主类,虚拟机会先执行该主类

5.当使用JDK1.7的动态语言时,如果一个methodHandler实例最后的解析结果的方法句柄所对应的类没有初始化则必须先出发初始化。

注意第1点中的标红部分。当我使用Singleton这个类得到单例的时候,我只能通过调用Singleton.getInstance()这个静态方法得到单例。问题就出在这个地方,根据第1点规则,只有当我调用Singleton.getInstance()这个静态方法的时候,Singleton类才会完成初始化。也就是说只有当我调用Singleton.getInstance()这个静态方法的时候,才会执行

private static Singleton instance = new Singleton(); 

这句代码从而new出一个Singleton对象。

那我如果不使用这个单例对象的话内存中根本没有Singleton实例对象,又怎么说是饿汉模式呢,占用资源又体现在哪里呢?和静态内部类的懒汉模式又有什么区别呢?

懒汉模式代码:

	private Singleton() {} 
	private static class LazyHolder {
		private static Singleton instance = new Singleton();
	}
	public static Singleton getInstance() {
		return LazyHolder.instance;
	}

使用内部静态类来实现,classloader加载机制保证了线程安全,只有在调用getInstance的时候也就是LazyHolder.instance这个静态变量被访问的时候LazyHolder类才会进行静态变量的初始化(new Singleton()),之后其他的线程才可以访问。

我的理解是这样的,饿汉模式的时候,只有在Singleton中有其他静态变量或静态方法,并且这个静态变量或静态方法是在getInstance()方法被访问前就已经被访问或者调用,这个时候触发了类的初始化,之后内存中才存在这个Singleton单例对象了。要不然就是根据规则2,对单例模式进行反射调用,如果是静态内部类的懒汉模式,则不会new出这个单例对象,但是饿汉模式就会先new出这个单例对象。其他情况的话饿汉模式的写法和静态内部类的懒汉模式的写法是没有区别的。

如果理解有错误,或有不同的见解,欢迎在评论区指出。谢谢~

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值