【设计模式-—单例模式】

定义及应用场景

单例模式指的是保证一个类仅有一个实例,并提供一个全局访问点。单例模式是创建型模式。应用场景如下:

  1. 连接池
  2. spring中的applicationContext 应用上下文

单例模式的几种写法

饿汉式单例

饿汉式单例模式在类加载的时候就初始化了,并且创建了单例对象,是线程安全的,因为它类加载的时候已经初始化了,在线程出现之前,不可能出现

//饿汉式
public class HungrySingleton{
	private static final HungrySingleton lan=new HungrySingleton();
	private HungrySingleton (){}
	//全局访问点
	public static HungrySingleton getInstance(){
		return lan;
	}
}

缺点:在类加载的时候就初始化对象,可能会造成内存浪费。

静态内部类单例

静态内部类能解决上述懒汉式造成的内存浪费,既能保证懒加载,又线程安全。

public class StaticInnerClassSingleton{
	private static class SingletonHolder{
		private static final StaticInnerClassSingleton INSTANCE=new StaticInnerClassSingleton();
	}
	private StaticInnerClassSingleton(){
		//防止反射破坏单例
		if(SingletonHolder.INSTANCE!=null){
			throw new RuntimeException("不允许创建多个单例");
		}
	}
	//全局访问点
	public static final StaticInnerClassSingleton getInstance(){
		return SingletonHolder.INSTANCE;
	}
}
懒汉式单例

懒汉式单例,如其名一样比较懒,只有在使用时才会初始化,下面看下简单实现

//懒汉式单例
public class LazySingleton(){
	private static LazySingleton lazy=null;
	private LazySingleton (){}
	public static LazySingleton getInstance(){
		//此处2个线程进入此方法可能会造成线程不安全
		if(lazy==null){
			lazy=new LazySingleton();
		}
		return lazy;
	}
}

缺点:如果在多线程的情况下,可能有2个线程同时进入到if方法中,2个线程都在if判断时,先后进入if判断并先后返回值。

双重校验锁

出现了线程不安全的懒汉式单例,有人就会说在类的方法上添加,synchronized关键词,这样会导致锁的范围很大,这样效率很低,于是有了双重检验锁。简单实现如下:

public class DouSingleton{
	private static DouSingleton singleton;
	private DouSingleton(){}

	public static DouSingleton getInstance(){
		if(singleton==null){
			synchronized(DouSingleton.class){
				if(singleton==null){
					singleton=new DouSingleton ();
				}
			}
		}
		return singleton;
	}
}

缺点:可能会造成空指针异常,解决方式是在单例对象加volatile关键字。 若不太清楚请搜索有关java内存模型的知识,这里简单说明一下,创建对象分3步:a、开辟空间;b、初始化对象信息;c、返回对象的地址给引用。volatile是防止这3个步骤的重排序。线程1 执行了ab步骤 ,线程2判断对象==null为false直接返回了对象,导致对象为空。

单例与序列化
public class Singleton implements Serializable{
	private static Singleton singleton;
	private Singleton(){}

	public static Singleton getInstance(){
		if(singleton==null){
			synchronized(Singleton.class){
				if(singleton==null){
					singleton=new Singleton ();
				}
			}
		}
		return singleton;
	}
	//只需重写这个方法。
	private Object readResolve(){
		return singleton;
	}
}
枚举式单例

此方式是Effective Java作者提倡的方式,它能避免多线程同步问题,还可以防止反序列化重新创建新的对象。

public enum EnumSingleton{
	INSTANCE;
	EnumSingleton(){}
	public static EnumSingleton getInstance(){
		return INSTANCE;
	}
}
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值