单例模式
结构 单例类Singleton,在单例类的内部创建它的唯一实例,并通过静态方法getInstance()让客户端可以使用它的唯一实例;为了防止在外部对单例类实例化,将其的构造函数的可见性设置为private;在单例类的内部定义了一个Singleton类型的静态对象作为供外部共享访问的唯一实例。 适用环境 系统只需要一个实例对象;客户调用类的单个实例只允许使用一个公共访问点,除了该访问点,不能通过其他途径访问该实例。 饿汉式单例实现 当类被加载时,静态变量instance会被初始化,此时类的私有构造函数会被调用,单例类的唯一实例被创建。
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {
}
public static EagerSingleton getInstance(){
return instance;
}
}
懒汉式单例实现,这种技术又称为延迟加载(Lazy Load)技术 与饿汉式单例类不同的是,懒汉式单例类在第一次被引用时将自己实例化,在懒汉式单例类被加载时不会将自己实例化。
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton(){}
synchronized public static LazySingleton getInstance(){
if(null == instance){
return new LazySingleton();
}
return instance;
}
}
双重检查锁定 懒汉模式在单线程环境下是可行的,但是如果放到多线程高并发环境就不可行了,故提出双重检查锁定。需要注意的是,如果使用双重检查锁定来实现懒汉式单例类,需要在成员变量instance之前增加volatile修饰符,被volatile修饰的成员变量可以确保多个线程都能够正常处理,且该代码只能在JDK1.5以上的版本才能正确运行。
public class LazySingletonDoubleCheckLock {
private static LazySingletonDoubleCheckLock instance = null;
private LazySingletonDoubleCheckLock(){}
public static LazySingletonDoubleCheckLock getInstance(){
//第一次非空检查
if(null == instance){
//锁定代码块
synchronized (LazySingletonDoubleCheckLock.class){
//第二次非空检查
if(null == instance){
instance = new LazySingletonDoubleCheckLock();
}
}
}
return instance;
}
}
最后来个重量级单例模式实现方式,使用静态内部类实现单例模式IODH 饿汉式单例类不能实现延迟加载,不管将来用不用始终占用内存;懒汉式单例类线程安全控制烦琐,而且性能受到影响。可见,无论是饿汉还是懒汉模式,都存在一些问题,为了克服这些问题,引出静态内部类,既可以实现延迟加载,又能保证线程安全性,线程安全由java虚拟机保证。
public class Singleton {
private Singleton(){}
private static class StaticInnerClass{
private static final Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return StaticInnerClass.instance;
}
}