设计模式之单例模式
有一些对象我们只需要一个,如果创建了多个实例,有可能会出现各种问题,比如线程池、注册表、缓存等等,这个时候就要用到单例模式了。一开始我以为单例模式会很容易,不就是把构造方法设为私有再提供一个静态方法去获取这个实例嘛,然而仔细了解后我才发现事情并没那么简单,它居然有好几种写法……
1.定义
单例模式(Singleton Pattern)确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。
单例模式的要点有三个:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。单例模式是一种对象创建型模式。单例模式又名单件模式或单态模式。
2.实例说明
2.1 饿汉模式
1 | public class Singleton { |
这种方式在类加载的时候直接完成初始化,因此类加载会有点慢,但是获取对象的速度快,而且可以避免多线程的同步问题。
2.2 懒汉模式(线程不安全)
1 | public class Singleton { |
先判断有没有实例,没有的话再创建实例。这种没有考虑到线程安全,多线程的时候可能会同时构造多个对象。
你可能想到了,我们在getinstance()方法前加锁同步不就得了嘛……所以就有了下面这种写法。
2.3懒汉模式(线程安全)
1 | public class Singleton { |
这个时候每个线程进入到getinstance()方法之前都要等别的线程离开该方法,这得浪费多少资源啊……这种方式的效率是比较低的。
2.4 双重检查模式
1 | public class Singleton { |
这种模式对进行了两次判空,第一次是为了不必要的同步,第二次是在singleton等于null的情况下才创建实例。并且使用了volatile关键字,虽然牺牲了一点性能,但是提高了准确性。
2.5 静态内部类
1 | public class Singleton { |
第一次加载Singleton类时并不会初始化instance,只有第一次调用getInstance方法时虚拟机加载SingletonHolder 并初始化instance ,这样不仅能确保线程安全也能保证Singleton类的唯一性,推荐使用静态内部类单例模式。
2.6 其它
除此之外还有枚举单例和容器实现单例,不过我不是很熟,这里就不写了……等什么时候熟一点了我再写写吧!