Android 单例模式的使用
来源:互联网 发布:程序源码交易 编辑:程序博客网 时间:2024/05/16 14:50
有时候我们需要使用一个实用类A,这个类A专门提供一些公共功能供别人调用,而本身并不会处理业务逻辑。由于类A会被许多类乃至线程调用,假设我们的程序非常庞大,在运行的过程中,会访问这个类A100次,为了调用类A的方法,需要先创建A的对象,A a = new A()。这种方法在对A的访问量较少的情况下没问题,但是像我们这种情况,就会创建100个类A的实例,这100个实例是要占用内存的,从这种角度来说,就造成了大量不必要的开销。而单例模式,在整个程序生命周期中,只有一个实例,这样就不会造成不必要的内存消耗。
单例模式的设计
为了让整个生命周期内只有一个实例,我们可以这样做:
- public class Singleton {
- private static Singleton sSingleton;
- private Singleton() {
- }
- public static Singleton getInstance() {
- if (sSingleton == null) {
- sSingleton = new Singleton(); // line A
- }
- return sSingleton;
- }
- }
- public class Singleton {
- private static Singleton sSingleton;
- private Singleton() {
- }
- public static Singleton getInstance() {
- synchronized (Singleton.class) {
- if (mSingleton == null) {
- sSingleton = new Singleton();
- }
- return sSingleton;
- }
- }
- }
我们需要看一下上述代码,真的需要每次进入getInstance方法都要获得锁吗?其实不是的,整个Singleton类中,对mSingleton进行访问的地方分为两类:读和写,而且仅当mSingleton为null的时候才会写,mSingleton一旦创建完毕,后面就只剩下读操作了,再怎么高并发也没什么关系了,反正mSingleton已经是现成的,直接读就可以了,看如下采用double-check机制的改进代码:
上述代码近乎完美,可以满足几乎所有场合(采用反射和类加载器另当别论)。上述代码的好处在于:第一次创建实例的时候会同步所有线程,以后有线程再想获取Singleton的实例就不需要进行同步,直接返回实例即可。还有double-check的意义在于:假设现在有2个线程A和B同时进入了getInstance方法,线程A执行到line A行,线程B执行到line B行,由于B线程还没有初始化完毕,sSingleton还是null,于是线程A通过了sSingleton==null的判断,并且往下执行,碰巧,当线程A执行到line C的时候,线程B初始化完毕了,然后线程B返回,注意,如果没有double-check,这个时候线程A就执行到了line B,就会再次初始化sSingleton,这个时候Singleton实际上被new了两次,已经不算完全意义上的单例了,而有了double-check,就会再进行一次为null的判断,由于B线程已经初始化了sSingleton,所以A线程就不会再次初始化sSingleton。
- public class Singleton {
- private volatile static Singleton sSingleton;
- private Singleton() {
- }
- public static Singleton getInstance() {
- if (sSingleton == null) { // line A
- synchronized (Singleton.class) { // line C
- if (sSingleton == null)
- sSingleton = new Singleton(); // line B
- }
- }
- return sSingleton;
- }
- }
double-check(DCL)在很大程度上可以满足高并发的需要,尽管如此,它还是有一些小缺点的,问题的关键在于尽管得到了Singleton的正确引用,但是却有可能访问到其成员变量的不正确值,这听起来有点抽象,不过没关系,我们只是需要有个感性的认识就好,如果你真的好奇,那么请搜索“java happen-before”。既然DCL单例模式以中彩票的概率存在一些小问题,那么有没有所谓的完美的解决方案呢?答案是有,在给出之前,我要说的是:单例有很多种写法,我们不能简单地否定其他写法,尽管它们看起来不能很好地处理高并发情况,也许它们本来就是用于低并发情形下的。下面请看一种所谓完美应用于高并发情形下的单例写法,静态内部类单例模式:
- public class Singleton
- {
- private Singleton(){
- }
- private static class InstanceHolder{
- private static final Singleton instance = new Singleton();
- }
- public static Singleton getInstance(){
- return InstanceHolder.instance;
- }
- }
阅读全文
0 0
- Android - 单例模式(singleton)的使用
- Android - 单例模式(singleton)的使用
- Android多种单例模式的使用
- Android单例模式的使用
- android单例模式的使用
- Android 单例模式的使用
- android 单例模式和策略模式的结合使用
- Android中使用很广的模式-单例模式
- Android中正确使用单例模式及单例模式下的性能处理
- android 的单例模式
- Android的单例模式
- Android 使用单例模式有可能引起的内存泄露
- 单例模式的使用
- 单例模式的使用
- 单例模式的使用
- 单例模式的使用
- 单例模式的使用
- 单例模式的使用
- 欢迎使用CSDN-markdown编辑器
- Spring管理事务默认回滚的异常是什么?
- 2017年中OTT运营大数据蓝皮书
- CCF 201604-4 游戏
- JAVA中线程同步的方法(7种)汇总
- Android 单例模式的使用
- jvm源码阅读笔记[2]:你不知道的晋升阈值TenuringThreshold详解
- 小小萌新,刚学指针,写一个指针入门只有一点,哇咔咔
- uva-1476 Error Curves 三分
- matlab2c使用c++实现matlab函数系列教程-rot90函数
- poj2432 Anniversary party 入门级树形dp
- CCF 201512-1 数位之和
- AndroidStudio 目录结构
- Html动态时钟实例