Java 单列模式 懒汉饿汉 双重锁问题

1.饿汉模式

//饿汉单例模式
//线程安全 调用效率高 不能延迟加载
public class SingletonHungry {
	//私有化构造器---不能再外部生成该类的对象,只用通过指定的接口才能得到
	private SingletonHungry() {
		
	};
	
	//提供静态成员变量,在类加载的时候初始化
	private static SingletonHungry sh = new SingletonHungry();
	
	//提供获取静态成员对象的方法
	public static SingletonHungry getInstance() {
		return sh;
	}
}

2.懒汉模式

//懒汉模式
//线程安全 调用效率不高 可以延时加载
public class SingletonLazy {

	//私有化构造方法
	private SingletonLazy() {};
	
	//声明静态成员
	private static SingletonLazy sl;
	
	//定义获得实例的方法
	//添加synchronized关键字是为了保证线程安全--=对该方法进行加锁
	public static synchronized SingletonLazy getInstance() {
		if(sl==null) {//起到了延时加载的作用
			sl = new SingletonLazy();
		}
		return sl;
	}
	
	/*
	 * 之所以加synchronized关键字是因为如果一个线程通过了if判断,
	 * 在实例化的之前,另一个线程也通过了if判断,那么就会生成
	 * 两个不同的对象,而synchronized就保证了这个方法是同步的,
	 * 在被线程占用的情况下,另一个线程是不能访问的
	 */
	/*
	 * 但是synchronized会很耗费cpu资源,其实只有第一次进行初始化
	 * 的时候才用加锁
	 */
}

3.双重锁检测问题

//双重检测锁

public class SingletonDoubleLock {

	//私有化构造方法
	private SingletonDoubleLock() {};
	
	//提供未初始化的静态成员
	private volatile static SingletonDoubleLock sd = null;
	
	//声明获得实例的方法
	public static SingletonDoubleLock getInstance() {
		if(null == sd) {
			synchronized (SingletonDoubleLock.class) {
				if(null == sd) {
					sd = new SingletonDoubleLock();//problem
				}
			}
		}
		return sd;
	
	}
	/*
	 * 虽然上面的方法解决了cpu消耗大的问题,但是由于jvm底层内部
	 * 模型的原因,有一个隐患。
	 * 标记为problem的那行,实际在运行中可以分为三个步骤:
	 * 1.分配内存空间 2.初始化对象 3.将对象指向刚分配的内存空间
	 * 但是有些编译器为了性能之类的原因,可能将第二步和第三部重排序
	 * 就是jvm重排序问题,导致了问题。这时如果sd刚指向内存空间但是没有
	 * 初始化,那么sd不为空但是没有值,如果这个时候另一个线程访问该实例
	 * 不为空,但是没有值就会报错,这时就要在声明sd这个对象的时候
	 * 加上volatile关键字 将重排序禁止就好
	 */
}
//参考文章:https://www.cnblogs.com/xz816111/p/8470048.html
//			https://blog.csdn.net/betonme/article/details/86527654



4.静态内部类实现懒汉模式

//静态内部实现---属于懒汉模式
//线程安全	懒加载	只有真正调用getInstance才会加载静态内部类,线程安全
//static final 保证了内存中只有一个实例存在,而且只能被赋值一次
//爆炸了线程安全性 兼备了高并发和延迟加载的优势
public class SingletonStaticClass {

	private SingletonStaticClass() {
		System.out.println(System.currentTimeMillis());
	};
	
	private static class SingletonClassInstance{
		
		private static final SingletonStaticClass instance = new SingletonStaticClass();
	}
	
	private static SingletonStaticClass getInstance() {
		return SingletonClassInstance.instance;
	}
	
}

以上四个代码段分别描述了四种实现单例模式的方法及其优缺点,希望对你有所帮助。如有描述错误的地方,请指出,后期会更正。

发布了1 篇原创文章 · 获赞 1 · 访问量 15

猜你喜欢

转载自blog.csdn.net/qq_41962032/article/details/105611440