本文为阅读《Head First 设计模式》一书的摘要总结
单件模式
定义
单件模式 确保一个类只有一个实例,并提供一个全局访问点。

示例
public class Singleton{
private static Singleton uniqueInstance;
private Singletion(){
uniqueInstance = new Singleton();
}
public static Singleton getInstance(){
if (uniqueInstance == null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
上面的例子中,Singleton类的构造器的访问修饰符为private,这意味着我们不能在其他对象中通过new操作符来实例化这个对象。另外提供了一个静态的getInstance方法,该方法通过判断静态变量uniqueInstance是否为空来觉得是否实例化Singleton对象。我们通过调用getInstance方法,就可以得到Singleton单件。
在单线程应用中上面的代码没有问题,但是在多线程应用中,可能就会出现问题了。
在多线程应用中,假设Singleton还没有创建实例。现在线程1调用getInstance方法,当通过判断uniqueInstance==null之后,在实例化对象之前被剥夺了CPU,线程2开始调用getInstance,并获得了Singleton实例。当线程2被剥夺CPU之后,线程1继续执行,此时,uniqueInstace将会引用新的实例。
为了解决这个问题,我们只需要将getInstance改为同步方法:
public static synchronized Singleton getInstance(){
if (uniqueInstance == null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
这样,每次调用getInstance方法,都需要等待其他线程退出该方法之后,当前线程才能进入该方法。但是这便降低了性能。实际是,该方法只有第一次执行时需要同步,一旦设置好uniqueInstace变量的引用,就不需要同步这个方法了。
- 若是应用程序可以忍受同步带来的效率下降,那么我们就可以不用做任何修改
- 前面的例子采用的是延迟实例化,我们可以采用 预实例化,来消除多线程带来的问题:
public class Singleton{
private static Singleton uniqueInstance = new Singleton();
private Singletion(){}
public static Singleton getInstance(){
return uniqueInstance;
}
}
- 双检查加锁:如果十分关注性能,该方法能大大减少
getInstance的耗时。
public class Singletion{
private volatile static Singletion uniqueInstance;
private Singleton(){
}
public static Singleton getInstance(){
if (uniqueInstace == null){
synchronized(Singletion.class){
if (uniqueInstance == null){
uniqueInstace = new Singleton();
}
}
}
return uniqueInstace;
}
}
本文深入解析单件模式,确保一个类仅有一个实例并提供全局访问点。探讨了单线程和多线程环境下实例化的问题及解决方案,包括同步方法、预实例化和双检查加锁等策略。
221

被折叠的 条评论
为什么被折叠?



