Singleton Pattern 单态模式。
这个模式较简单,就是为了保证一个类只有一个实例,用一个入口来获取该实例。
例子如下(代码来自维基):
class Foo {
private static Helper helper = null;
private Foo(){}
public static Helper getHelper() {
if (helper == null)
helper = new Helper();
return helper;
}
// other functions and members...
}
由于构造方法设为了私有,所以其它类无法使用new 来生成该类实例,只有通过
该类自己提供的方法来获取实例。这个获取实例的方法通总是使用第一次创建的
实例而保证其它类总是使用同一个实例。
本来很简单,但是在多线程情况下则会有些麻烦。两个线程都有可能执行到了第
6行,这样就有可能创建2个实例。过程如下(线程1简称为T1,线程2 简称T2):
T1 5 (5代表第5行)
T2 5
T1 6
T1 7 (线程1返回一个实例)
T2 6
T2 7 (线程2返回另一个实例)
这样就破坏了实例唯一性。如果这两个实例状态不会变化,倒也无所谓,就是多
花点内存养两个对象。但如果这两个实例涉及到计数器等状态变化,就埋下了隐患。
解决办法是加上同步关键字,如下:
public static synchronized Helper getHelper() {
if (helper == null)
helper = new Helper();
return helper;
}
问题是解决了,但效率却降低了。因为每次获取实例都会执行同步运算。实际上
没必要。一旦实例创建并返回,以后再获取实例就不会执行第6行。为了发生几率
很小的事件而每次同步的方法,代价太大了。
不同虚拟机对同步方法的执行效率不同,早期虚拟机执行同步效率非常的低。现
在改进了很多,但进入线程体、离开线程体、加锁、解锁这些步骤仍然耗费性能。
所以,后来发明了双检查锁模式。(Double-Checked Locking Pattern)。在
《DesignPatternsExplained》一书中,作者专门分析了这种方法的优势,并给出
了代码。代码如下:
class USTax {
private static USTax instance;
private synchronized USTax(){};
public static USTax getlnstance () {
if(instance== null)
instance= new USTax();
return instance;
}
}
不想,书上印错了,这让很多人包括我迷惑良久。后来书本经过更正,变为如下形式,
class USTax {
private static USTax instance;
private USTax(){};
public static synchronized void doSyn(){
if(instance== null){
instance= new USTax();
instance.setSomething();}//这句是我加的,为方便接下来的解释。
}
public static USTax getlnstance () {
if(instance== null)
doSyn();
return instance;
}
}
到此,算是万事大吉了。不料这种双重检查模式仍然有问题,并不能解决多线程
的问题。由于这本书的广泛流传,这种模式也广为人知。当这种模式的错误之处
被发现后,很快就出现了对这种模式广泛的讨伐之声。可见,影响越大,一旦有
错,被讨伐的力度也就越大。
我们以上面这段代码为例,看看问题是怎样产生的,
T1 10 (线程1执行到第10行)
T1 5
T1 6
T2 10
T2 12
也就是说,线程1还没有完全构造完这个对象(还没有执行第7行),线程2就返回
这个半成品对象了。所以,这种谬种流传的 Double-Checked Locking Pattern也
就寿终正寝,不能再被使用了。
那这种多线程出现的问题该怎么做呢,解决方法也很简单,如下即可,
class USTax {
private static USTax instance = new USTax();
private USTax(){};
public static synchronized void doSyn(){
if(instance== null)
instance= new USTax();
}
public static USTax getlnstance () {
return instance;
}
}
分享到:
相关推荐
Singleton pattern单例模式应用
设计模式之Singleton(单态)
singleton pattern 的定义 主要应用方法 优缺点 通过代码 具体分析解释
单态模式的定义: Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。 在项目的很多地方都会用到它,比如说数据库的链接。 使用Singleton的好处还在于可以节省内存,因为它限制了实例...
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个...
单态模式的设计和应用--设计模式之Singleton(单态)
Head First 设计模式 (五) 单件模式(Singleton pattern) C++实现
4、单例模式(Singleton Pattern) 用意:仅允许生成一个对象时
Java据说有23种设计模式,Android的设计模式肯定是由Java来引申出来的。这里不讨论有多少人全会,有多少种设计模式会使用到,我们来讲下其中用得最多的也就是人人都知道的...这里是一个简单的SingletonPatternDemo。
DataSource的单态模式(SingleTon)程序---马克-to-win java视频 数据源 单态模式 dataSource Singleton
前端大厂最新面试题-Singleton Pattern.docx
单态模式 马克-to-win Java视频 Singleton 单例模式
单态模式 马克-to-win java视频 Singleton 单例模式
单态模式 马克-to-win java视频 Singleton 单例模式
设计模式之Singleton(单态
Singleton ( 单态模式 ) Builder ( 建造者模式 ) Prototype ( 原型模式 ) Adapter ( 适配器模式 ) Bridge ( 桥接模式 ) Composite ( 组合模式 ) Decorator ( 装饰模式 ) Facade ( 外观模式 ) Flyweight ( 享...
主要介绍了Java设计模式之单态模式(Singleton模式)介绍,本文讲解了如何使用单例模式、使用单例模式注意事项等内容,需要的朋友可以参考下
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 学习demo
NULL 博文链接:https://lym6520.iteye.com/blog/695374
备忘录模式(Memento Pattern) 策略模式(Strategy Pattern) 抽象工厂模式(Abstract Factory Pattern) 代理模式(Proxy Pattern) 单例模式(Singleton Pattern) 迭代器模式(Iterator Pattern) 访问者模式(Visitor ...