单例模式,想必很多人都不陌生;在经历过一段时间的移动开发后,几乎每个人都会封装积累自己的工具包,因此单例模式也是几乎必然出现的高频使用对象。
单例模式的好处不言而喻, 整个工程只创建一个对象, 这么做极大的消减了内存开销,深受广大开发玩家的喜爱;然而凡事有利则必有弊端, 单例模式最大的弊端可以是static带来的全局的生命周期,极易造成内存泄漏问题;因此警醒一些刚入门的玩家,不要在对象创建过程中,附带太多逻辑操作;如果是必然的,建议另起方法分离出来。
网络上的单例模式,分为很多种; 虽然实现方式各不相同,但是达到的目的是一致的;本篇不包含全部,够用即可。
1. 饿汉式
这是一个急性子的写法, 好处是线程安全的,因为类加载过程是线程安全的,饿汉式在类加载时就实例化;不好是做不到按需加载,会造成一定的性能浪费。
2. 懒汉式
好处是实现了按需加载,只有在使用时才会实例化; 不好是完全不是线程安全的,因此要考虑使用场景。
3. 静态内部类式(推荐)
眼前一亮!!!这种写法是推荐写法之一,既保证了懒汉式的懒加载(为什么 ? 静态内部类只有在引用后才会装载到内存),又保证了线程的安全性(为什么 ? 类加载过程是线程安全的)。
4. 双重校验式
懒汉式的改进版, 通过加锁来保证线程安全;双重判断保证实例是空的,为什么 ? 且听分解
1、有人问了,为什么不在方法上加锁呢?
答: 加锁是为了保证实例化过程的线程安全, 然实例化只有第一次调用才会执行,如果在方法上加锁,则任何获取的过程都是带锁的, 除第一次外,都是性能的损耗;加锁保证了线程安全,但同样也会造成性能的负担。
2.又有人问了,为什么要判断两次才行呢, 一次不够吗?
答: 当然不够。 第一次判断是为了确保是否加锁,因为对象已经存在的情况下,是不需要加锁的;第二次判断是为了确保对象是空的,锁块的执行是涉及多线程的,因此在锁中重新判断是必须的一步。
虽然说了这么多,但是该实现不能完全保证线程安全,因此,了解一下应付面试,不推荐使用!!!
5. 双重校验改进式
以上改进来自InputMethodManager, 通过把第一次加锁的实例化和以后的获取分离开,来保证懒加载的同时,也能保证绝对的线程安全,因此推荐这种写法。
由于Android不推荐枚举的使用,虽然Java大力推荐,但是还是决定不写了。希望通过本篇文章,可以帮助看到这篇文章的人,理解单例模式下面的一些细节与原理,更好的运用到项目中。
如果你觉得这篇文章对你又帮助,请帮我打call,不胜感激!