定义

单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点(静态方法)。单例模式属于创建型模式。常见的ServletContext、ServletContextConfig、ApplicationContext以及数据库的连接池等都是以单例形式存在的。

常见的单例模式

  • 饿汉式
    饿汉式单例是在类加载的时候就立即初始化,并且创建单例对象。绝对线程安全,在线程还没出现以前就是实例化了,不会存在访问安全问题。
    优点:没有加任何的锁、执行效率比较高,在用户体验上来说,比懒汉式更好。
    缺点:类加载的时候就初始化,不管用与不用都占着空间,浪费了内存空间。


代码示例如下:

public class HungrySingleton {
	private static final HungrySingleton hungrySingleton = new HungrySingleton();
	private HungrySingleton(){}
	//全局访问点
	public static HungrySingleton getInstance(){
    	return hungrySingleton;
	}
}

还可以利用静态代码块来实现:

public class HungryStaticSingleton {
	private static final HungryStaticSingleton hungrySingleton;
	static {
		hungrySingleton = new HungryStaticSingleton();
	}
	private HungryStaticSingleton(){}
	public static HungryStaticSingleton getInstance(){
		return hungrySingleton;
	}
}
  • 懒汉式
    懒汉式单例是在被外部类调用时才创建实例。
    示例如下:

public class LazySimpleSingleton {
	private LazySimpleSingleton(){}
	private static LazySimpleSingleton lazy = null;
	public static LazySimpleSingleton getInstance(){
		if(lazy == null){
			lazy = new LazySimpleSingleton();
		}
	return lazy;
	}
}

不过,上面的单例存在线程安全隐患,为了保证线程安全,我们可以采用双重检查锁的机制:

public class LazyDoubleCheckSingleton {
	private volatile static LazyDoubleCheckSingleton lazy = null;
	private LazyDoubleCheckSingleton(){}
	public static LazyDoubleCheckSingleton getInstance(){
		if(lazy == null){
			synchronized (LazyDoubleCheckSingleton.class){
				if(lazy == null){
					lazy = new LazyDoubleCheckSingleton();
				}
			}
		}
		return lazy;
	}
}

但是,用到synchronized关键字,总归是要上锁,对程序性能还是存在一定影响的。我们可以从类初始化角度来考虑,采用静态内部类的方式:

public class LazyInnerClassSingleton {
	private LazyInnerClassSingleton(){}
	public static final LazyInnerClassSingleton getInstance(){
		return LazyHolder.LAZY;
	}
	private static class LazyHolder{
		private static final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton();
	}
}
09-02 05:26