【技巧】Android单例模式改进

【技巧】Android单例模式改进

Android开发过程当中,为了节省不必要的内存开销,常常会使用到单例模式。
即,整个程序的生命周期当中,某个类只有一个实例,节省内存空间。

单例模式使用场景

该类专门提供一些公共功能供别人调用,而本身并不会处理业务逻辑。

Step1:常见单例模式

public class ClassA {
	private static ClassA mInstance;

	// 私有化构造函数,防止外部调用
	private ClassA() {

	}

	// 获取对象
	public static ClassA getInstance() {
		if (null == mInstance) {
			mInstance = new ClassA();
		}
		return mInstance;
	}
}

【成果】能够保证程序运行过程中,Class A类只有一个实例。
【问题】多线程情况下,两个线程同时并发调用getInstance()方法,且同时执行到了mInstance = new ClassA();语句。这样情况下还会各自new一个ClassA对象出来,没有完全实现单实例。

Step2:引入线程锁

为了解决Step1中的问题,我们可以引入线程锁,将实例化语句锁住。这样多个线程进入getInstance()方法后,开始抢mInstance的所有权,剩下的线程等待。

public class ClassA {
 	private static ClassA mInstance;
 	// 私有化构造函数,防止外部调用
	 private ClassA() {

 	} 

	// 获取对象
	public static ClassA getInstance() {
		synchronized (Singleton.class)  {
			if (null == mInstance) {
				mInstance = new ClassA();
			}
			return mInstance;
		}
	}
}

【成果】有效解决了高并发情况下的单实例保证问题。
【问题】高并发情况下,多个线程会在线程锁位置开始等待,如果线程个数较多,则等待时间较长的线程会出现明显堵塞现象,迟迟无法返回。如果该线程需要返回数据给UI,还会出现ANR现象。

Step3:引入Double Check机制

为了解决Step2中的问题,我们引入Double Check机制,只有mInstance为null的时候,才进行new操作,才有必要进行线程锁;一旦mInstance被创建,那么就没有必要进行线程加锁处理了。

public class ClassA {   
	private static ClassA mInstance;   

	// 私有化构造函数,防止外部调用   
	private ClassA() {     

	}  
	
	// 获取对象
 	public static ClassA getInstance() {
 		if (null == mInstance) {
  			synchronized (Singleton.class)  {
   				if (null == mInstance) {
    					mInstance = new ClassA();
	   			}
   				return mInstance;
  			}
 		}
 	}
}

【成果】问题解决
【代码说明】第一次创建实例的时候会同步所有线程,以后有线程再想获取mInstance实例就不需要同步,直接返回实例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值