定义
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例的使用场景
在一个系统中,要求一个类有且仅有一个对象,具体使用场景如下:
单例模式的6六种写法
1. 饿汉模式
1 | public class Singleton { |
优点:
- 这种方式在类加载时就完成初始化了,获取对象但速度快。
- 避免多线程但同步问题。
缺点:
- 类加载较慢。
- 没有达到懒加载的效果,如果从始至终都未使用果这个实例,这会造成内存的浪费。
2. 懒汉模式(线程不安全)
1 | public class Singleton { |
优点:
- 节省资源
缺点:
- 第一次实例化对象时较慢。
- 多线程时不能正常工作。
3. 懒汉模式(线程安全)
1 | public class Singleton { |
优点:
- 多线程中很好的工作。
缺点:
- 每次调用
getInstance
方法时都需要同步,这会造成不必要的同步开销。大部分时候我们是用不到同步的,所以,不建议用这种模式。
4. 双重检查模式
1 | public class Singleton { |
优点:
- 资源利用率高。
- 避免多余同步。
- 线程安全。
缺点:
- 使用了
volatile
或多或少会影响性能。 - 第一次实例化对象时较慢。
- 在高并发某些情况下会出现失效问题。
DCL
(Double Check Lock) 在高并发环境下也会有一定的缺陷,DCL
虽然在一定程度上解决了资源的消耗、多余的同步、线程安全问题等问题,但还是在某些情况会出现失效的问题,也就是DCL
失效。这里建议用静态内部类单例模式来代替DCL
。
5. 静态内部类单例模式 (推荐使用)
1 | public class Singleton { |
第一次加载
Singleton
类时并不会初始化sInstance
。 只有在第一次调用getInstance
方法时虚拟机才会加载SingletonHolder
并初始化 sInstance。
优点:
- 资源利用率高。
- 避免多余同步。
- 线程安全。
缺点:
- 暂无
6. 枚举单例
1 | public enum Singleton { |
优点:
- 任何情况下都是单例。
- 默认线程安全。
缺点:
- 简单
- 可读性不高。
总结:到这里6种单例写法已介绍完,至于选择那种形势的单例模式,取决与你项目本身情况:是否复杂的高并发环境,或者是否需要控制单例对象的资源消耗。
本文原创出自 https://giantss.github.io/blog/2018/11/13/Java设计模式之单例模式/ 翻版必究