设计模式:单例模式

什么是单例模式?

单例是指在程序运行的整个环境中仅存在一个实例,比如构建线程池的线程工厂、配置文件的管理器、数据库连接池的管理器等等,在这些场景下,一般为了节省内存或保证原子语义,只需要在环境中构建一个实例即可,单例模式(singleton pattern)就是为了实现单例的一种代码设计模式。

Java代码如何实现?

//饿汉式单例
//优点:①简单实用;②JVM保证线程安全(同一类只会加载一次)
//缺点:无论使用与否,类加载时就已经完成了实例化,占用内存
public class Mgr01{
	//1.定义一个final的静态属性
	private static final Mgr01 INSTANCE = new Mgr01();
	
	//2.将构造方法私有化
	private Mgr01(){}

	//3.提供一个获取实例的静态方法
	public static Mgr01 getInstance(){
		return INSTANCE;
	}
} 

//饿汉式单例:与Mgr01一样
public class Mgr02{
	//1.定义一个final的静态实例
	private static final Mgr02 INSTANCE;
	
	//2.将实例的初始化延迟
	static{
		INSTANCE = new Mgr02();
	}
	
	//3.将构造方法私有化
	private Mgr02(){}
	
	//4.提供一个获取实例的静态方法
	public static Mgr02 getInstance(){
		return INSTANCE;
	}
}

//懒汉式单例
//优点:解决饿汉式缺失懒加载的问题
//缺点:引入了线程不安全问题(在判断null时,一个线程判断了但没有执行new,其他线程判断了也执行了new,但第一个线程还是会执行new,最终导致获取的实例并不是单例)
public class Mgr03{
	//1.定义一个的静态属性(这里不能使用final,因为final修饰的类属性必须马上初始化)
	private static Mgr03 INSTANCE;
	
	//2.将构造方法私有化
	private Mgr03(){}

	//3.提供一个获取静态实例的静态方法	
	public static Mgr03 getInstance(){
		//4.获取时检查实例是否已经完成初始化
		if(null == INSTANCE){
			INSTANCE = new Mgr03();
		}
		return INSTANCE;
	}
}

//加锁懒汉式单例
//优点:通过synchronized加锁解决了懒汉式单例的线程不安全问题
//缺点:效率相对较低,因为每一次访问都会加解锁
public class Mgr04{
	//1.定义一个静态属性
	private static Mgr04 INSTANCE;
	
	//2.构造器私有化
	private Mgr04(){}
	
	//3.提供一个获取实例的静态方法
	public static synchronized Mgr04 getInstance(){
		if(null == INSTANCE){
			INSTANCE = new Mgr04();
		}
		return INSTANCE;
	}
}

//锁细化懒汉式单例
//优点:缩小锁的粒度
//缺点:并不能实现单例(已经将null判断与new分离)
public class Mgr05{
	//1.定义一个静态属性
	private static Mgr05 INSTANCE;
	
	//2.构造器私有化
	private Mgr05(){}
	
	//3.提供一个获取实例的静态方法
	public static Mgr05 getInstance(){
		if(null == INSTANCE){
			synchronized(Mgr05.class){
				INSTANCE = new Mgr05();
			}
		}
		return INSTANCE;
	}
}

//双重检查懒汉式单例(DCL)
//优点:缩小了锁的粒度
//缺点:写法较为复杂,实现缺失优雅
public class Mgr06{
	//1.定义一个静态属性(使用volatile禁止指令重排,防止未初始化就返回)
	private static volatile Mgr05 INSTANCE;
	
	//2.构造器私有化
	private Mgr06(){}
	
	//3.提供一个获取实例的静态方法
	public static Mgr06 getInstance(){
		if(null == INSTANCE){
			synchronized(Mgr06.class){
				if(null == INSTANCE){
					INSTANCE = new Mgr04();
				}
			}
		}
		return INSTANCE;
	}
}

//内部类式单例:
//优点:懒加载且线程安全(JVM保证同一个类只会加载一次)
//缺点:暂无
public class Mgr07{
	//1.构造方法私有化
	private Mgr07(){}
	
	//2.私有静态内部类:静态内部类只有在用到时才会被初始化
	private static class Mgr07Inner{
		private final static Mgr07 INSTANCE = new Mgr07();
	}
	
	//3.提供一个获取单例的静态方法
	public static Mgr07 getInstance(){
		return Mgr07Inner.INSTANCE;
	}
}

//枚举式单例
//优点:简单且防止住了反序列化
//缺点:优点违背枚举的语义,一般很少在枚举中写业务方法
public enum Mgr08{
	INSTANCE;
}

版权声明:本文为weixin_43647393原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。