yao__shun__yu转载的一篇博客详细的介绍了实现单例模式的几种方法:http://blog.csdn.net/generalfu/article/details/8142463,对性能和线程安全的阐述写得特别好。lz自己也把单例模式写了写,但不免还是会有些疏忽,本文主要是写写自己的心得和以及自己觉得还需注意的地方,对原文的第5小节也提出了一点改进,算是这篇文章的一点补充吧。
单例模式的含义为一个Singleton类只有它自身的一个实例。本文1-4小节就性能和线程安全方面易出现的问题进行了探讨,对此有兴趣的读者可以参考其中的内容。第5小节提出了较好的解决方案,想了解的读者也可以直接看这里,第5小节不以1-4小节为基础。
首先,对yao__shun__yu转载的博客中的要点概括如下:
1.饥饿模式:使用了静态工厂方法,对象设为static,在声明时便初始化了,在getSingleInstance方法中直接返回该对象,可能带来潜在的性能问题。
public final class EagerSingleton
{
private static EagerSingleton singObj = new EagerSingleton();
private EagerSingleton(){
}
public static EagerSingleton getSingleInstance(){
return singObj;
}
}
2.懒汉模式:使用了延迟加载方法,对象设为static,在声明时设为null,在使用时,在getSingleInstance方法中,如果对象为null则初始化,解决了性能问题,但是是线程不安全的。
public final class LazySingleton
{
private static LazySingleton singObj = null;
private LazySingleton(){
}
public static LazySingleton getSingleInstance(){
if(null == singObj ) singObj = new LazySingleton();
return singObj;
}
}
3.在懒汉模式的getSingleInstance方法前加Synchronized,解决了线程安全问题,但是并发度较低。
public final class ThreadSafeSingleton
{
private static ThreadSafeSingleton singObj = null;
private ThreadSafeSingleton(){
}
public static Synchronized ThreadSafeSingleton getSingleInstance(){
if(null == singObj ) singObj = new ThreadSafeSingleton();
return singObj;
}
}
4.Double-Checked Lock:只对创建对象的语句进行同步,可以得到很好的并发度,但是可能会得到未完整初始化的对象。因为初始化需要一定时间,如当线程A未完全初始化对象时,此时对象已经不是null了,线程B在第9行判断对象不为null后就可能返回一个未完全初始化的对象。
public final class DoubleCheckedSingleton
{
private static DoubleCheckedSingletonsingObj = null;
private DoubleCheckedSingleton(){
}
public static DoubleCheckedSingleton getSingleInstance(){
if(null == singObj ) {
Synchronized(DoubleCheckedSingleton.class){
if(null == singObj)
singObj = new DoubleCheckedSingleton();
}
}
return singObj;
}
}
5.Initialization-on-demand holder:使用一个静态类SingletonHolder来初始化Singleton对象(注意是Singleton对象而不是SingletonHolder对象噢,原因请参看本文最开始的单例模式定义),SingletonHolder只在被使用时才被初始化,保证了性能和线程安全。并且由于java的构造方法默认是public的,需要将Singleton的构造方法写成private,避免其他类直接调用Singleton的构造方法获取实例。
public class Singleton
{
private Singleton(){
}
private static class SingletonHolder
{
public final static Singleton instance = new Singleton();
}
public static Singleton getInstance()
{
return SingletonHolder.instance;
}
}