天天看点

单例模式(Singleton)理解

一、为什么要用单例模式

   当一个类需要用来管理共享资源的时候,我们就只需要一个对象,比方说:线程池、缓存、日志对象等等。如果说制造出了多个实例,就会导致许多问题的产生,例如:程序异常,资源使用过量,结果不一致等等。

   举个简单的例子就是,当一个web应用中连接数据库的Connection对象,如果每次访问都new一个出来,那么当有一万个甚至更多的访问在短时间内并发,这将导致服务器资源的大量开销,因为这些对象不回被垃圾回收立刻收回。但如果服务器对此只实例化一次,每次Connection对象被使用后放回线程池,其他访问过来时在重新使用它,这便使得服务器性能大大的提升了,这里就要用单例模式去实现程序了。

二、金典单例模式实现

*注意:金典单例实现只适用于单线程的情况,当有多个线程并发时,它们都要执行这段代码,都执行到第6行,这时sl都为空,于是乎就会实例出多个对象了,这就违背了单例模式的思想了。

三、多线程场景下的单例模式

1.大家很容易想到在getInstance()方法上加上synchronized关键字就能解决线程并发时的问题了。

*注意:但是我们可以想象得到,真正需要同步的是在第一次调用时,之后就不再需要同步这个方法了。之后的每次调用,同步都会是一种累赘。程序执行的效率就会大大降低。

2.使用“急切”创建实例,而不用延迟延迟实例化的做法

JVM虚拟机在加载这个类时就会立马创建此唯一的单例。

3.使用“双重加锁”,在getInstance()方法中减少使用同步

这样就能延迟创建实例,并且是线程安全的。

四、总结

   为了保证能在多线程场景下程序不会出错,通常我们应该选择后两种实现方式中的一种。至于具体用哪种更好,这个可以更具具体的需求来定:

   1.程序总是创建并使用单例时,选择“急切”创建实例的实现吧。

   2.如果不是1,就用“双重加锁”吧。

   最后,在单线程的情况下,还是推荐使用金典。金典感觉总是挺好的。嘿嘿。

继续阅读