几种单例模式
程序员文章站
2022-07-13 23:39:38
...
几种单例模式
枚举可以天然防止反射和反序列化漏洞 需要延时加载时:枚举好于饿汉式 ,不需要延时加载:静态内部类好于懒汉式 也就是说优先选用 枚举和静态内部类
饿汉
/**
* 饿汉式单例设计模式
* 特点:线程安全、调用效率高、资源利用率低(无懒加载)。
*
* @author tiger
* @Date 2017年9月2日
*/
public class SingletonHungry {
// 私有构造函数
private SingletonHungry() { }
// 单例对象,static是天然的线程安全
private static SingletonHungry instance = new SingletonHungry();
// 静态的工厂方法(访问本类的唯一入口)
public static SingletonHungry getInstance() {
return instance;
}
}
懒汉1
对方法添加synchronized
/**
* 懒汉式单例设计模式||特点:线程安全、调用效率低、资源利用率高(有懒加载)。
* @author tiger
* @Date 2017年9月2日
*/
public class SingletonLazy {
// 私有化构造器
private SingletonLazy() {}
private static SingletonLazy instance = null;
// 对方法进行同步(synchronized)并发效率低。
public synchronized static SingletonLazy getInstance(){
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}
懒汉2
静态内部类
/**
* 静态内部类单例子模式
* 特点:线程安全、兼备了高并发和延迟加载优势(有懒加载)。
*
* @author tiger
* @Date 2017年9月2日
*/
public class SingletonLazyInnerClass {
// 私有构造函数,杜绝反射机制破坏
private SingletonLazyInnerClass() {
if (LazyHolder.LAZY != null) {
throw new RuntimeException("不允许创建多个实例");
}
}
// 在静态内部类里创建类的实例
private static class LazyHolder {
private static final SingletonLazyInnerClass LAZY = new SingletonLazyInnerClass();
}
// 提供一个外界调用的公共方法,需要调用的时候才会初始化静态内部类,不需要线程同步,从而兼备了
// 高并发需求
public static final SingletonLazyInnerClass getInstance() {
// 在返回结果以前,一定会先加载内部类
return LazyHolder.LAZY;
}
}
懒汉3
双重检测锁+volatile
/**
* 懒汉模式 -》 双重同步锁单例模式
* 单例实例在第一次使用时进行创建
*/
public class SingletonDoubleCheck {
// 私有构造函数
private SingletonDoubleCheck() { }
// 1、memory = allocate() 分配对象的内存空间
// 2、ctorInstance() 初始化对象
// 3、instance = memory 设置instance指向刚分配的内存
// 单例对象 volatile + 双重检测机制 -> 禁止指令重排
private volatile static SingletonDoubleCheck instance = null;
// 静态的工厂方法
public static SingletonDoubleCheck getInstance() {
if (instance == null) { // 双重检测机制 // B
synchronized (SingletonDoubleCheck.class) { // 同步锁
if (instance == null) {
instance = new SingletonDoubleCheck(); // A - 3
}
}
}
return instance;
}
}
懒汉4-推荐
枚举
/**
* 枚举模式:最安全
*/
public class SingletonEnum {
// 私有构造函数
private SingletonEnum() { }
public static SingletonEnum getInstance() {
return LazyHolder.INSTANCE.getInstance();
}
// 枚举内部类
private enum LazyHolder {
INSTANCE;
private SingletonEnum singleton;
// JVM保证这个方法绝对只调用一次
LazyHolder() {
singleton = new SingletonEnum();
}
public SingletonEnum getInstance() {
return singleton;
}
}
}