GOF之单例模式

何为单例模式?

通常点说就是一个类只有一个实例,这意味着其构造函数是私有的。

这里让我想到了spring ioc管理的bean,默认也是单例的。不过这里的概念跟设计模式里的单例不一样,ioc里的bean被设计成单例

在于为了servlet容器初始化spring容器时降低内存开销。

spring ioc还有个关注点:被注入的bean可以是原生对象,也可以是被aop增强的代理对象(也就是说在ioc容器里的原生对象并不对外提供服务)。

 

单线程下的单例

单例代码一(懒汉模式),性能比饿汉的好一些 懒加载思想很多地方都用到,比如spring 、dubboz中@Reference(lazy=true)

public class Singleton {

	private static Singleton singleton = null;//懒汉=先不创建实例
	private Singleton(){
    
    }
	public static Singleton getInstance() {
		if(null == singleton) {
			singleton =  new Singleton();
		}
		return singleton;
	}
}

此为最基本的。

单例代码二 (饿汉模式)

public class Singleton{
	private static final Singleton singleton = new Singleton();//饿汉

    //介绍一种变种的写法
    /*private static Singleton singleton = null;
    
    static{
        singleton = new Singleton();
    }
    */
	private Singleton() {
		
	}
	public static Singleton getInstance() {
		return singleton;
	}
}

以上两段代码在单线程下没啥问题,但是多线程就不行了。

引入两个线程:A和B.

当A线程进入代码一getInstance方法,刚判断对象为null,此时cpu切换到线程二执行,然后B检测到也为null然后创建对象,过程结束后cpu切换到A继续(因为A之前检测为null)所以直接创建实例了。最终得到两个实例,违反了单例原则。

继续优化实现饿汉式,接下来加入了懒加载思想

public class Singleton{
	
	private static class SingletonHolder{
		private static final Singleton singleton = new Singleton();
	}
	
	private Singleton() {
		
	}
	public Singleton getInstance() {
		return SingletonHolder.singleton;
	}
}

对比之前饿汉式,都是由Singleton类装载时就初始化好了实例,而现在只有当执行getInstance方法才会去内部类获取到实例,所以延迟了事先获取实例体现了懒加载思想。

多线程下的单例

单例代码三(以下只对懒汉的研究,饿汉性能差就算了)


public class Singleton{
	private static  Singleton singleton = null;
	private Singleton() {
		
	}
	public static synchronized Singleton getInstance() {
		if(null == singleton) {
			singleton = new Singleton();
		}
		return singleton;
	}
}

该段代码以同步方式实现了了线程安全,由于是在方法上加synchronized,所以一旦线程多了就阻塞等待很长时间,所以性能也偏抵。

对以上代码进行调优:

public class Singleton{
	private static  Singleton singleton = null;
	private Singleton() {
		
	}
	public  static Singleton getInstance() {
		if(null == singleton) {//这个也很重要
           
			synchronized(Singleton.class) {
                 if(null == singleton){//这个很重要
				   singleton = new Singleton();
			     }
			
            }
		}
		return singleton;
	}
}

该代码通过先判断对象是否null,若为null则A线程获取锁B线程也等待,A执行完轮到B(此时对象已经不为null了),此时B进入代码块后又判断是否为null,结果不是,最终也返回对象。这边两个null判断是关键。这个完美实现了

思想在于:double---checked----locking 。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值