单例模式
单例模式:确保一个类只有一个实例,并提供一个全局访问点。
单例模式的三种写法
方法一:同步getInstance()方法(俗称“懒汉”,延迟式)
public class Singleton {
private static Singleton singleton = null;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
而事实上,只有第一次执行getInstance方法时,才真正需要同步,因此同步是一种累赘,当调用该方法频繁时,大大影响性能。
方法二:急切实例化方法(推荐)(俗称“饿汉”)
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() {
}
public static synchronized Singleton getInstance() {
return singleton;
}
}
利用这个做法,我们依赖JVM在加载这个类时马上创建此唯一的单例实例。如果应用程序总是创建并使用单例实例,或者在创建和运行时的负担不太繁重,可以采用该方式。
方法三:双重检查锁方法(推荐)
public class Singleton {
private static volatile Singleton singleton = null;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
volatile关键字确保:当singleton变量被初始化成Singleton实例时,多个线程正确地处理singleton变量。
该方法不适用与JAVA1.5之前的版本。
针对上述三种方法,我一般使用第三种方法。当然,针对不同的情形,可以采用适当的方法。
单例模式要点:
1. 单例模式确保程序中一个类最多只有一个实例
2. 单例模式也提供访问这个实例的全局点
3. 在JAVA中实现单例模式需要私有的构造器、一个静态方法、一个静态变量
4. 确定在性能和资源上的限制,然后小心的选择适当的方案来实现单例,已解决多线程的问题
5. 如果JAVA版本低于1.5,双重检查锁实现会失效
6. 如果使用多个类加载器,可能导致单例失效而产生多个实例
7. 如果JAVA版本低于1.3,必须建立单例注册表,以免垃圾收集器将单例回收