单例模式
总结单例的几种写法:
1 静态内部类,这种方式利用了classloder的机制来保证初始化instance时只有一个线程,支持延迟加载和线程安全
public class CommonRpcHttpServer{
private static class SingletonHolder {
static final CommonRpcHttpServer instance = new CommonRpcHttpServer();
}
public static CommonRpcHttpServer getInstance() {
return SingletonHolder.instance;
}
}
2 (懒汉,线程不安全)
public class ProcessFactory {
private static ProcessFactory singleton = null;
public ProcessFactory() {
super();
}
public static ProcessFactory singleton() {
ProcessFactory.singleton = (ProcessFactory) Class.forName("ProcessFactory").newInstance();
return singleton;
//return new ProcessFactory()
//通过class.forname().newInstance()和new ()方式的效果一致,前者进行实例化的好处是解耦,增加代码的复用性和扩展性,但只能调用无参的构造函数,后者 强类型,效率高,可以调用任何public构造函数,但强耦合。
}
3(懒汉,线程安全),增加同步块约束
public class ProcessFactory {
private static ProcessFactory singleton = null;
public ProcessFactory() {
super();
}
public static synchronized QuoteProcessFactory singleton() {
ProcessFactory.singleton = (ProcessFactory) Class.forName("ProcessFactory").newInstance();
return singleton;
}
4 饿汉,静态域直接初始化,不支持延迟加载
public class ProcessFactory {
private static ProcessFactory singleton = new ProcessFactory() ;
//private static ProcessFactory singleton = null;
//{singleton = new ProcessFactory() ;}
public ProcessFactory() {
super();
}
public static ProcessFactory singleton() {
return singleton;
}
5 双重校验锁,注意volatile 修饰单例对象,否则还是会出现同步问题。在JDK1.5及其后续版本中,扩充了volatile语义,系统将不允许对 写入一个volatile变量的操作与其之前的任何读写操作 重新排序,也不允许将 读取一个volatile变量的操作与其之后的任何读写操作 重新排序。
public class ProcessFactory {
private static volatile ProcessFactory singleton = null;
public ProcessFactory() {
super();
}
public static ProcessFactory singleton() {
if(singleton == null){
synchronized(ProcessFactory.class){
if(singleton == null){
return new ProcessFactory ();
}
}
}
}
总结: 总的来说,有五种写法,懒汉,恶汉,双重校验锁,枚举(用的比较少,未举例)和静态内部类,个人倾向静态内部类。
延伸连接,双重检验锁的弊端:http://www.xker.com/page/e2011/0422/101056.html