Java 单例模式 - 双重判断、内部类、枚举

 ================================

©Copyright 蕃薯耀 2022-05-20

蕃薯耀的博客_CSDN博客

 

一、饿汉模式


public class Hunger {

	/**
	 * 增加final关键字,避免被修改
	 */
	private static final Hunger hunger = new Hunger();
	
	/**
	 * 私有化,避免创建对象
	 */
	private Hunger() {};
	
	/**
	 * 提供获取对象的方法
	 * @return
	 */
	public static Hunger get() {
		return hunger;
	}
	
	
}

二、饿汉模式(静态块)

可以通过配置文件对实例进行初始化


import lqy.utils.PropertiesUtils;

public class HungerStatic {


	private static final HungerStatic hungerStatic;
	
	private String name;
	
	/**
	 * 私有化,避免创建对象
	 */
	private HungerStatic(String name) {
		this.name = name;
	};
	
	
	static {
		String name = PropertiesUtils.readKeyValue("config.properties", "name");
		hungerStatic = new HungerStatic(name);
	}
	
	
	/**
	 * 提供获取对象的方法
	 * @return
	 */
	public static HungerStatic get() {
		//System.out.println(hungerStatic);
		return hungerStatic;
	}


	/*
	@Override
	public String toString() {
		return "HungerStatic [name=" + name + "]";
	}
	*/
	
	
}

三、懒汉模式 - 同步方法

public class LazySafe {

	private static LazySafe lazySafe;
	
	private LazySafe() {}
	
	public static synchronized LazySafe get() {
		if(lazySafe == null) {
			lazySafe = new LazySafe();
		}
		
		return lazySafe;
	}
	
}

四、懒汉模式 - 同步块


public class LazySync {

	/**
	 * 需要加volatile防止指令重排
	 */
	private static volatile LazySync lazySync;
	
	private LazySync() {}
	
	public static LazySync get() {
		synchronized (LazySync.class) {
			if(lazySync == null) {
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				lazySync = new LazySync();
			}
		}
		return lazySync;
	}
}

五、懒汉模式 - 双重判断


public class LazySyncDouble {

	/**
	 * 需要加volatile防止指令重排
	 */
	private static volatile LazySyncDouble lazySyncDouble;
	
	private LazySyncDouble() {}
	
	public static LazySyncDouble get() {
		if(lazySyncDouble == null) {
			synchronized (LazySyncDouble.class) {
				if(lazySyncDouble == null) {
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					lazySyncDouble = new LazySyncDouble();
				}
			}
		}
		return lazySyncDouble;
	}
}

六、懒汉模式 - 内部类


/**
 * Inner是一个内部静态类,当外部类 LazyInner 被加载的时候,并不会创建 Inner实例对象。
 * 只有当调用 get() 方法时,Inner才会被加载,这个时候才会创建 instance。
 * instance 的唯一性、创建过程的线程安全性,都由 JVM 来保证。
 * 所以,这种实现方法既保证了线程安全,又能做到延迟加载。
 * @author islee
 *
 */
public class LazyInner {

	private LazyInner() {}
	
	/**
	 * 静态内部类
	 *
	 */
	private static class Inner{
		private static final LazyInner lazyInner = new LazyInner();
	}
	
	public static LazyInner get() {
		return Inner.lazyInner;
	}
}

七、枚举【最安全方式】

最安全,能预防反射和反序列化的安全问题


/**
 * Java虚拟机会保证枚举类型不能被反射并且构造函数只被执行一次。
 * [最安全],其他的会存在反射和反序列化的安全问题
 *
 */
public class SingletonEnum {

	private SingletonEnum() {}
	
	private enum SingletonHolder {

		INSTANCE;
		
		private final SingletonEnum singletonEnum;
		
		private SingletonHolder() {
			singletonEnum = new SingletonEnum();
		}
		
		private SingletonEnum get() {
			return singletonEnum;
		}
	}
	
	
	public static SingletonEnum get() {
		return SingletonHolder.INSTANCE.get();
	}
	
}

测试:


import lqy.design.singleton.SingletonEnum;

public class SingletonEnumTest {

	public static void singletonEnum() {
		long startTime = System.currentTimeMillis();
		
        for(int i=0; i<15; i++){
            new Thread(()-> {
                System.out.println(SingletonEnum.get());
            }).start(); 
        }
        
        long endTime = System.currentTimeMillis();
        System.out.println("耗时:" + (endTime - startTime));
    }
    
    public static void main(String[] args) {
        singletonEnum();
        
    }
}

 (时间宝贵,分享不易,捐赠回馈,^_^)

================================

©Copyright 蕃薯耀 2022-05-20

蕃薯耀的博客_CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值