设计模式学习004——单例模式Singlton

单例模式:当一个类被设计成单例模式后,就可以保证任何时候,该类对应的实例永远就只有一个对象。

那如何实现单例呢?只要保证如下几点就可以了。

第一:一定不可以让用户通过关键字new来创建对象。(只提供private的构造器)

第二:该类要提供一个接口给外界使用此类的对象。(getInstance()方法)

下面我们给出我们的代码:

public class SingltonInstance {
	private static SingltonInstance singltonInstance;
	private SingltonInstance(){
	}
	public static SingltonInstance getInstance(){
		if(singltonInstance == null){
			singltonInstance = new SingltonInstance();
		}
		return singltonInstance;
	}
}
看以上代码,我们在getInstance方法中判断了我们的类变量singltonInstance是否为空,如果为空就赋值,如果不为空就直接返回去,从而保证了SingltonInstance的类永远只有一个实例。

恩。咋一看,还是那么回事。。。。But......真的是这样的吗?

单线程的情况下,确实如此,但是如果是多线程呢?如果两个线程都执行到了if判断处,这个时候,如果就容易出现多个线程都去初始化SingltonInstance实例。此时,就会产生多个对象实例。此时我们就有解决方案:

方案一:同步方法,代码如下:

public class SingltonInstance {
	private static SingltonInstance singltonInstance;
	private SingltonInstance(){
	}
	public static synchronized SingltonInstance getInstance(){
		if(singltonInstance == null){
			singltonInstance = new SingltonInstance();
		}
		return singltonInstance;
	}
}
这下可以了吧。确实可以,但是我们知道,同步方法会带来很大性能影响。如果同步我们上面的getInstance方法,每一次一个线程要用该类的实例的时候,都需要去同步,这样性能岂不是很受影响???的确如此!!因为上面的同步控制真正发挥作用的时候是在第一次实例化singltonInstance的时候,一旦实例化了这个变量以后,以后的同步都是多余的。

方案二:预先初始化类的实例变量,代码如下:

public class SingltonInstance {
	private static SingltonInstance singltonInstance= new SingltonInstance();
	private SingltonInstance(){
	}
	public static SingltonInstance getInstance(){
		if(singltonInstance == null){
			singltonInstance = new SingltonInstance();
		}
		return singltonInstance;
	}
}
上面的代码会在类加载到内存中的时候,就直接实例化一个对象,所以此时就不需要同步了,因为singltonInstance实例始终不为空,始终可以保证不会因为线程引起混乱。但是这个方案与上面的方案相比明显存在的一个弊端就是:这个类一旦加载到内才能就实例化了一个对象,使用的是“急切实例化”,而不是“延迟实例化”。延迟实例化的方案的好处就是真正的需要的时候才实例化对象。

方案三:既采用“延迟实例化”,又避免同步造成性能的影响:代码如下:

public class SingltonInstance {
	private static volatile SingltonInstance singltonInstance;
	private SingltonInstance(){
	}
	public static SingltonInstance getInstance(){
		if(singltonInstance == null){
			synchronized (SingltonInstance.class) {
				if(singltonInstance == null)
				 singltonInstance = new SingltonInstance();
			}
		}
		return singltonInstance;
	}
}
此处采用了“双重检查锁”(Double-Check locking)机制,在singltonInstance为空的时候,就去实例化它,但是实例化的时候要同步,并且在同步方法里面要再次检查一下看在当前线程进入到同步方法之前这段时候是否有其他线程已经初始化了singltonInstance变量。这样就保证了绝对只有一个实例存在。而加入volatile关键字就是在处理多线程时,能保证singltonInstance能够被正确的实例化。而不会引起混乱。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值