一 介绍
单例模式是保证系统实例唯一性的重要手段。单例模式首先通过类的实例化方法私有化来防止程序通过其他手段创建该类的实例,然后通过提供一个全局唯一获取该类实例的方法帮助用户获取类的实例,用户只需也只能通过调用该方法获取类的实例。
二 实现
常见单例模式的实现有以下4种:懒汉模式(线程安全)、饿汉模式,静态内部类,双重校验锁。
(1)懒汉模式
定义一个私有静态对象instance,之所以定义一个instance为静态,是因为静态属性或方法是属于类的,能够很好地保障单例对象的唯一性;然后定义一个加锁的静态方法获取对象,如果该对象为null,则定义一个对象实例并将其赋值给instance,这样下次在获取该对象便能够直接获取。
代码实现:
public class Singleton {
private static Singleton instance;
private Singleton(){}
public static synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
(2)饿汉模式
在类中直接定义全局的静态对象的实例并初始化,然后提供一个方法获取该实例对象。懒汉模式和饿汉模式最大不同点在于:懒汉模式在类中定义了单例但是并未实例化,实例化的过程是在获取单例对象的方法中实现的,也就是说,在第一次调用懒汉模式时,该对象一定为空,然后去实例化对象并赋值,这样下次就能直接获取对象;而懒汉模式是在定义了单例对象的同时将其实例化,直接使用。
在饿汉模式下,在ClassLoder完成后该类的实例便已经存在于JVM中:
public class HungrySingleton {
private static HungrySingleton instance = new HungrySingleton();
private HungrySingleton(){}
public static HungrySingleton getInstance(){
return instance;
}
}
(3)静态内部类
通过在类中定义一个静态内部类,将对象实例的定义和初始化放在内部类中完成,在获取对象时要通过静态内部类调用其单例对象。这样设计是因为类的静态内部类在JVM中唯一,很好地保障了单例对象的唯一性。
public class Singleton {
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
private Singleton(){}
public static final Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
}
(4)双重校验锁
双锁模式在懒汉模式基础上改进,给静态对象的定义加上volatile锁来保障初始化时对象的唯一性,在获取对象时通过synchronized(Singleton.class)给单例类加锁来保障操作的唯一性。
public class Lock2Singleton {
private volatile static Lock2Singleton singleton;
private Lock2Singleton(){}
public static Lock2Singleton getInstance(){
if(singleton == null){
synchronized (Singleton.class){
if(singleton == null){
singleton = new Lock2Singleton();
}
}
}
return singleton;
}
}