Head First 设计模式之单例模式(Java例子)

前言:

来源于《head first 设计模式》。当作读书笔记了,这次看的是第五章装单例模式。连续看了两章,下一章预告命令模式。单例模式看着简单,但其中的道理并不少。

单例模式的概念

用于确保一个类只有一个实例,并提供全局访问点。

由于过于简单吧,跳过日常举例子的环节,直接写出一步步演变的单例模式

经典单例模式
public class Singleton {
	private static Singleton uniqueInstance;
 	//私有化构造方法
	private Singleton() {}
 	//提供全局访问点
	public static Singleton getInstance() {
		if (uniqueInstance == null) {
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	}
 
	// other useful methods here
	public String getDescription() {
		return "I'm a classic Singleton!";
	}

上述实现方法属于延迟实例化(lazy instantiaze),利用private让构造方法私有化,static修饰getInstance提供全局访问。
不过把这个简单单例模式存在一定的弊端哦,就是在多线程模式的时候,会产生不同的实例变量。
例如:有两个线程。线程一执行getInstance进入到判断uniqueInstance是否为null,为null准备实例化,此时跳转到线程二执行,线程二判断uniqueInstance==null,也是为null,也进入了实例化过程。=。=这就gg公司了啊,线程二创建完实例化对象后,执行其他方法,而到线程一的时候又创建实例化对象覆盖,执行其他方法。此时可能会把单例模式对象的一些初始化数据又出初始化了。
那么只能引入同步咯或者先初始化

解决同步的单例模式
  • 先初始化
public class Singleton {
	private static Singleton uniqueInstance = new Singleton();
 
	private Singleton() {}
 
	public static Singleton getInstance() {
		return uniqueInstance;
	}
	
	// other useful methods here
	public String getDescription() {
		return "I'm a statically initialized Singleton!";
	}
}

直接在成员变量处让其初始化。。即类加载器加载此类的时候顺路初始化。这样就不会存在并发问题咯。

  • 引入同步
public class Singleton {
	private static Singleton uniqueInstance;
 
	// other useful instance variables here
 
	private Singleton() {}
 
	public static synchronized Singleton getInstance() {
		if (uniqueInstance == null) {
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	}
 
	// other useful methods here
	public String getDescription() {
		return "I'm a thread safe Singleton!";
	}
}

其实就是加入synchronized关键字,迫使每次只能一个线程访问此方法。但同时也带来了另外一个问题。降低了性能。我们不难发现一个问题,多线程并发问题只存在于对象的初始化阶段,往后的每次调用不需要同步啊。直接获取已实例化的对象。这样子的话同步貌似就成为了一种累赘。
那么如何改进呢?

public class Singleton {
	private volatile static Singleton uniqueInstance;
 
	private Singleton() {}
 
	public static Singleton getInstance() {
		if (uniqueInstance == null) {
			synchronized (Singleton.class) {
				if (uniqueInstance == null) {
					uniqueInstance = new Singleton();
				}
			}
		}
		return uniqueInstance;
	}
}

用volatile关键字,使uniqueInstance变量修改的时候每个线程都能够知道,不会出现脏读的现象。
判断为null后再进行同步。只有第一次初始化才会彻底执行完代码。初始化完成后,不会再进行同步的判断。

总结

单例模式的主要实现步骤就是1.私有化构造方法 2.提供访问点,加上注意多线程并发问题即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值