定义
单例模式(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();
}
}