欢迎来到无限飞翔,在这里,你会找到许多有趣的技术 : )

6 种单例写法,你会写几种?

Java 77℃

第一种:饿汉方式

优点:代码简单易读,由JVM类加载机制保证了线程安全,无需业务方关心。

缺点:无法做到延迟创建对象,在加载class的时候就会创建对象。

第二种:懒汉方式(线程不安全)

优点:代码简单易读。

缺点:在多线程情况下非现场安全,可能出现创建多个实例。

第三种:懒汉方式(线程安全)

优点:代码简单易读,线程安全。

缺点:每次调用时,都需要线程同步,性能较差。

第四种:内部类方式

优点:由JVM保证线程安全,不需要业务方关心。

缺点:第一次访问可能较慢,他需要加载内部类这样可能占用更多的code区域的内存。

第五种:枚举

枚举在单例上的使用较其他有点不太一样,使用示例如下:

Singleton.INSTANCE.doSomeThing();

优点:由JVM保证了线程安全,代码简洁。

缺点:代码不易理解。

Joshua Bloch大神较为推崇这种写法,他在《Effective Java》中明确表达过下面观点:

使用枚举实现单例的方法虽然还没有广泛采用,但是单元素的枚举类型已经成为实现Singleton的最佳方法。

第六种:双重校验锁

优点:线程安全

缺点:每次访问对象都需要判null,并且volatile导致每次都会访问主内存,性能相比较而言较差。该单例模式较容易出错,特别是volatile关键字要加,具体原因可以参考:Java面试官最喜欢问的关键字-volatile

总结

线程安全

性能

可读性

延迟加载

推荐使用不

恶汉

推荐

懒汉(非线程安全)

不推荐

懒汉(线程安全)

不推荐

内部类

一般

一般

枚举

一般

推荐

双重校验锁

一般

一般

一般

具体选择哪种方式肯定是具体场景具体分析;但是一般情况下,我是比较推荐恶汉和枚举方式。

大家如果阅读过JDK源码可能就会注意到,JDK主要采用的恶汉和懒汉模式,基本上不会采用枚举、双重校验锁;我猜测可能的原因双重双重校验锁再JDK1.5版本之前有问题并且枚举是在JDK1.5版本才引用的,导致历史上很多JDK在实现单例模式没有那么多选择。

其他很多开源项目在选择单例上就较为丰富,基本上每种单例都可能遇到,比如在Hystrix就遇到了恶汉模式(HystrixTimer)和内部类(HystrixPlugins)

转载请注明:无限飞翔 » 6 种单例写法,你会写几种?

喜欢 (0)or分享 (0)