1.延迟实例化
当我们不急切需要一个实例时,也就是当用户需要一个实例时,再创建实例。
a.同步低效率版
public class Singleton {
private static Singleton uniqueInstance;
//私有化构造方法,防止用户通过构造器构造
private Singleton(){}
//同步方法,同一时间,只允许一个用户调用该方法获取实例
public static synchronized Singleton getInstance(){
if (uniqueInstance == null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
这种写法虽然简单,但是效率低下,实际上同步只需要在实例未创建完成时起作用就可以,防止多线程使得多个用户得到不同的实例。而已经有了一个实例的时候,同步就不需要了。如果你不关心效率,就可以用该方法,简单清晰。
b.双重检查加锁
public class Singleton {
//volatile关键词确保:档uniqueInstance变量被初始化成Singleton实例时,多个线程正确的处理uniqueInstance变量
private volatile static Singleton uniqueInstance;
//私有化构造方法,防止用户通过构造器构造
private Singleton(){}
public static Singleton getInstance(){
if (uniqueInstance == null){//检查实例,如果不存在就进入同步区块,只有第一次才彻底执行这里的代码
synchronized (Singleton.class){
if (uniqueInstance == null){//进入区块后,再检查一次,如果仍是null,才创建实例。
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
2.急切实例化
在静态初始化中创建单价,保证了线程安全,用户需要用时,实例已经生成好。
public class Singleton {
private volatile static Singleton uniqueInstance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return uniqueInstance;
}
}