1.饿汉模式 – 线程安全,调用效率高
在类被加载时初始化instance,调用私有的构造函数,创建单例类的唯一实例。(不能延时加载)
(构造函数是私有的,因此该类不能被继承)
/*
* 饿汉模式
*/
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
//私有的构造函数
private EagerSingleton(){}
//getInstance()方法
public static EagerSingleton getInstance(){
return instance;
}
}
2.懒汉模式
类的构造函数是私有的,与饿汉模式不同,instance是在第一次被引用时进行实例化。(延时加载)
懒汉式有两种实现方式:线程安全和线程不安全的
a)第一种写法,在第一次被引用时进行实例化
/*
* 第一种写法,线程不安全
*/
public class LazySingleton1 {
private static LazySingleton1 instance = null;
//私有的构造函数
private LazySingleton1(){}
public static LazySingleton1 getInstance(){
if(instance==null){
instance = new LazySingleton1();//有可能有多个线程进入此状态,导致创建了多个实例。
}
return instance;
}
}
b)第二种写法
加入同步锁(synchronized)
/*
* 第二种写法,线程安全
*/
public class LazySingleton2 {
private static LazySingleton2 instance = null;
//私有的构造函数
private LazySingleton2(){}
/*加入同步锁,迫使每个线程在进入该方法前。要等候别的线程离开该方法,即不会有两个线程同时调用该方法
*缺点:只有第一次执行此方法时才需要同步,如果每次调用都同步,降低性能
*/
public static synchronized LazySingleton2 getInstance(){
if(instance==null){
instance = new LazySingleton2();
}
return instance;
}
}
3.双重检查加锁 –线程安全
首先检查实例是否已经创建了,未创建才进行同步
public class DoubleCheckLocking {
//volatile关键字确保实例化时多个线程能正确处理instance变量
private volatile static DoubleCheckLocking instance = null;
//私有构造函数
private DoubleCheckLocking(){}
public static DoubleCheckLocking getInstance() {
if(instance == null){//检查该实例是否存在,不存在则进入同步区块
synchronized (DoubleCheckLocking.class) {
if(instance==null){//进入同步区块后再检查一次,如果仍然不存在才创建实例
instance = new DoubleCheckLocking();
}
}
}
return instance;
}
}
4.静态内部类模式–线程安全,调用效率高
调用getInstance()方法时,才实例化instance
public class InnerclassSingleton {
//静态内部类
private static class InnerclassSingletonGetInstance {
public static final InnerclassSingleton instance = new InnerclassSingleton();
}
//私有构造器
private InnerclassSingleton() {
}
//只有调用getInstance()时,才会加载类InnerclassSingletonGetInstance,并实例化instance
public static InnerclassSingleton getInstance() {
return InnerclassSingletonGetInstance.instance;
}
}
5.枚举模式 – 线程安全 调用效率高
enum EnumSingleton {
INSTANCE;
}