设计模式学习笔记:单例(singleton)模式
From Wikipedia: the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object.
文中关于设计模式的描述与实现很可能跟Java语言特性有关。
单例模式是很简单的一种设计模式,它的主要目的是保证在程序运行过程中,某个特定的类只存在一个实例。很多时候,我们采用将类的成员和方法静态化也可以实现这样的需求。有的时候,这样做是无伤大雅的,但是有的时候采用静态方法来替代单利模式是不恰当的。且这还会跟具体的语言特性相关。
Java采用构造器来创建一个新的实例,因此只需要将构造器设为私有,便可以阻止其他类不负责任的随意构造实例,同时,我们还需要有一个静态的方法来返回或者构造一个实例。简单代码如下:
1 2 3 4 5 6 7 8 9 10 11 | public class Singleton{ private static Singleton foo; private Singleton(){} /* a lot of other codes here */ public Singleton getInstance(){ if(foo==null) foo=new Singleton(); return foo; } } |
可以看到,单例模式无论从概念上还是实现上都是比较简单的。但是,如果我们的代码运行在多线程环境中,会发生什么情况呢?如果运气足够的不好,方法getInstance()可能同时由几个线程在调用,而此时恰好foo还是null,那么就会创建多个实例。我们的getInstance方法不是线程安全的,如何解决呢?
方法1:getInstance()方法仅仅在实例还没有被创建的时候才会出现线程不安全的问题,如果我们非常早的就创建了实例,那么就没有这个问题了,比如这样:
1 | private static Singleton foo=new Singleton(); |
因此,解决单例模式线程安全问题一种方法就是非常早的实例化。
方法2:利用Java的同步机制,对getInstance()方法加锁,可以彻底避免线程安全问题,比如:
1 | synchronized getInstance(){.. |
,这种方法能解决问题,但是性能相当底下,不推荐使用。
方法3:同方法2一样的思路,只是不是对方法本身加锁,而只是对方法内部其中的一块加锁。这种特性只有Java5.0以后才支持。真正造成线程安全问题的是getInstance中创建实例的部分,只需要同步这部分即可。
1 2 3 4 5 6 7 8 | public Singleton getInstance(){ if(foo==null) { synchronized { if(foo==null) foo=new Singleton(); } } return foo; } |






1 Trackback(s)