单件模式一(Singleton Pattern):单件模式介绍
一、意图
二、适用性
1.当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
2.当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
三、结构
四、单件模式的经典实现
使用java实现单例模式如下:
-
package
com.pattern.singleton; -
-
public
class Singleton - {
-
private static Singleton null;uniqueInstance = -
-
//其他有用的实例变量 -
-
//构造方法是私有的,所以在类外不能new出多个实例 -
private Singleton() -
{ -
//初始化其他实例变量 -
} -
-
public static Singleton getInstance() -
{ -
if (uniqueInstance null)== -
{ -
uniqueInstance = new Singleton(); -
} -
return uniqueInstance; -
} - }
只有在首次使用这个类的实例时才会产生这个“单例”,否则永远不会产生,这就是“延迟实例化(lazy instantiaze)”;
五、处理多线程
可以看出在多线程情况下,上述的getInstance方法可能会返回不同的实例(比如两个线程同时判断出uniqueInstance为null,接下来就会产生两个不同的实例),为了解决这种情况,可以使用以下方法:
1.使用synchronized关键字将getInstance()方法变成同步方法
-
public
static synchronized Singleton getInstance() - {
-
if (uniqueInstance null)== -
{ -
uniqueInstance = new Singleton(); -
} -
return uniqueInstance; - }
2.使用“急切”创建实例,而不用延迟实例化
-
public
class Singleton - {
-
private static Singleton newuniqueInstance = Singleton(); -
private Singleton() -
{ -
//其他 -
} -
//在JVM加载该类时已经创建此唯一的单件实例 -
public static Singleton getInstance() -
{ -
return uniqueInstance; -
} - }
在静态初始化时创建单件,保证了线程安全。但是如果这个对象非常耗费资源,而在程序的执行过程中并没有使用到它,那就造成资源的浪费了。
3.用“双重检查加锁”,在getInstance()中减少使用同步
使用双重检查加锁(double-checked
locking),首先检查实例是否已经创建了,如果尚未创建,才进行同步,这样一来既实现了延迟实例化又避免了多线程同步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; -
} - }
注意:双重检查加锁不适用于1.4及更早的版本,在1.4及更早版本中许多JVM对volatile关键字的实现会导致双重检查加锁的失效。
六、其他
1.很多情况如:线程池、日志对象、数据库连接等,我们需要一个对象或者需要控制实例的个数时,应当使用单例模式。
2.在java 1.2之前,垃圾收集器会造成当单件在没有全局的引用时被当做垃圾清除,这样在调用getInstance()方法时会产生一个新的实例,一切都回到最原始的设置,单例模式就没有意义了。所以必须建立单件注册表以免垃圾收集器将单件收回。
3.因为每个类加载器都有自己的命名空间,不同的类加载器可能会加载同一个类,所以在使用单件模式时多个个类加载器可能有机会各自创建自己的单件实例,解决办法:自行指定类加载器,并指定同一个类加载器。
4.最好不要继承单件类。因为必须把单件的构造器改为public或protected,就不是真正的单件了。
5.全局变量和单件模式:
转载请注明出处:http://blog.csdn.net/jialinqiang/article/details/8847672