Just some sharing about java open source and life

Java设计模式之Singleton

日期:2010-07-09 23:14 | 作者:JavaChen | 分类目录:Java Core
106 views

Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。 singleton能够被状态化也能被无状态化,通常是用在工具类里,实现单线程的操作。

第一种:注册型的模式:

public class RegSingleton {
	static private HashMap m_registry = new HashMap();
	static {
		RegSingleton x = new RegSingleton();
		m_registry.put(x.getClass().getName(), x);
	}

	protected RegSingleton() {
	}

	static public RegSingleton getInstance(String name) {
		if (name == null) {
			name = "RegSingleton";
		}
		if (m_registry.get(name) == null) {
			try {
				m_registry.put(name, Class.forName(name).newInstance());
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		return (RegSingleton) (m_registry.get(name));
	}
}

第一种:饥渴型的模式:

public class EagerSingleton {
	private static final EagerSingleton m_instance = new EagerSingleton();

	private EagerSingleton() {
	}

	public static EagerSingleton getInstance() {
		return m_instance;
	}
}

第一种:懒汉型的模式:

public class LazySingleton {
	private static LazySingleton m_instance = null;

	private LazySingleton() {
	}

	public static LazySingleton getInstance() {
		if (m_instance == null) {
			synchronized (LazySingleton.class) {
				if (m_instance == null) {
					m_instance = new LazySingleton();
				}
			}
		}
		return m_instance;
	}
}

第一种方式很少有人使用,因为其没有考虑到多线程并发的情况;第二种方式,在自己内部定义自己一个实例,并提供了一个供外部访问本class的静态方法;第三种方式不用每次都进行生成对象,只是第一次使用时生成实例,提高了效率!仔细看第三种方式,其采用了双重验证m_instance是否为空的方式,并且在方法内部对对象加了同步方法。这种方式看清来万无一失,其实还是有欠妥的地方,深究下去,这就涉及到到double-checked locking (DCL)的讨论。具体讨论,可以参照以下文档:
Double-checked locking and the Singleton pattern
When is a singleton not a singleton?
从上面的文章,可以知道第三种方式并不能解决问题,在第三种方式的方法里设置临时变量也不能解决问题(因为虚拟机会进行优化操作),使用volatile 关键字也不是可靠的方法(因为不同虚拟机对其实现不一致),最可靠的的方法也是最初最容易想到和写出的方法也就是对方法加同步锁。虽然,对整个方法加同步锁,会耗很多资源,但是保证线程安全最可靠的方法了。
最可靠的方式:

public class LazySingleton {
	private static LazySingleton m_instance = null;

	private LazySingleton() {
	}

	public synchronized static LazySingleton getInstance() {
		if (m_instance == null) {
			m_instance = new LazySingleton();
		}
		return m_instance;
	}
}
作者:JavaChen | 分类目录:Java Core | 标签:
  1. 在最后那中方式,开销比较大,不是最好的方法;
    建议使用静态内部内的方式;

回到顶部

无觅相关文章插件,快速提升流量