单例模式
核心实现
1、构造方法私有化,使其不能在类外部通过new方法实例化该类;
2、定义一个private static的实例化对象;
3、定义一个静态方法用于返回该唯一对象;
饿汉模式(立即加载)
使用类的时候就已经将对象创建完毕,没有多线程同步的问题,但是会持续占着内存;
public class Singleton{
// 将自身实例化对象设置为一个属性,并且static、final修饰
private static final Singleton instance = new Singleton();
// 构造方法私有化
private Singleton(){}
// 静态方法返回该实例
public static Singleton getInstance(){
return instance;
}
}
懒汉模式(延迟加载)
调用get方法的时候才会创建对象,在多线程环境中,完全不能保证单例的状态;
public class Singleton{
// 将自身实例化对象设置为一个属性,并用static修饰
private static Singleton instance;
// 构造方法私有化
private Singleotn(){}
// 静态方法返回该实例
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
线程安全的懒汉模式
在多线程情况下保证了线程安全,但是synchronized效率很低
public class Singleton{
// 将自身实例化对象设置为一个属性,并用static修饰
private static Singleton instance;
// 构造方法私有化
private Singleton(){}
// 静态方法返回该实例,加synchronized关键字实现同步
public static synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
双端检索机制
DCL (Double check lock)也不一定安全,可能存在指令重排序;
多线程模式的单例模式
public class SingletonDemo{
// 加了volatile才是安全的
private static volatile SingletonDemo instance = null;
private SingletonDemo(){
}
// 双端检索机制
public static singletonDemo getInstance(){
// 线程2进来时,如果没有使用volatile修饰,可能线程1的a操作的1、3部分已经执行,instance不为null,但是没有具体引用;
if(instance == null){
synchronized(SingletonDemo.class){
if(instance == null){
// 这个new操作具体还有三步
// 1. 分配对象内存空间
// 2. 初始化对象
// 3. 设置instance指向的内存地址;
instance = new SingletonDemo(); // a操作
}
}
}
return instance;
}
}