手写单例模式以及保证安全性
单例模式的几个特点
- 为了确保全局只有一个类的实例,所以类的构造器要私有化
- 单例类必须由自己创建自己的唯一实例
- 单例类必须给其他对象提供这一个实例
单例模式是一个最简单的设计模式,属于创建型结构。比如我们 window 中的任务管理器,回收站,操作系统就是一个单例的设计。也就是说我们使用的对象永远是同一个。程序中的单例大致可以分为 4 大类。饿汉式、懒汉式、双重锁和静态内部类。我们先来说饿汉式
饿汉式
饿汉式是一个简单的写法,和名字一样。他很饿,饿的话救急着要东西。所以他会在类加载的时候就初始化。是一个线程安全的操作。但因为不是懒加载,所以不管我们用没用这个实例。他都会实例化。可能会造成一些不必要的内存。浪费内存资源。
1 | /** |
懒汉式
懒汉式和饿汉式相反。支持懒加载,也就是我们使用的时候才会去实例化对象。我们可以使用 synchronized 来保证饿汉式的线程安全。但是加锁自然会降低效率。我们大多数情况下是用不到同步的
1 | /** |
双重锁 (DCL)
为了解决以上两个类的弊端。我们的双重锁出现了。双重锁全名叫双重检查锁(Double checked locking of Singleton)
,和名字一样,会检查两次。由原本加在方法上的锁加载了内部,这样的话,只有第一次初始化的时候才会上锁。后续获取实例的时候就不会因为锁而影响性能。
1 | /** |
静态内部类
静态内部类也是一个很好用的实现单例的方法。本质上是通过类加载机制原理实现的延迟加载。当外部类被加载的时候,内部类并没有被加载,只有我们调用 getInstance () 这个方法才会去加载 StaticHolder () 这个方法。这个时候去创建实例。并且只会被实例化一次。做到了延迟化加载,线程安全。
1 | /** |
总结
我们一般使用后两种方法来创建实例 (双重锁 & 静态内部类),因为他们更安全,支持延迟化加载,效率更高并且不会浪费内存。我个人一般使用静态内部类,因为相对来说更简单一点
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Sora33!
评论