单件模式的定义
确保一个类只有一个实例,并提供一个全局访问点。
类图
单件模式.jpg1.其中uniqueInstance 变量持有唯一的单间实例
2.getInstance()方法是静态的,这意味着它是一个类方法,所以可以在代码的任何地方使用Singleton.getnstance()访问它。这样和访问全局变量一样,只是多了一个优点:单件可以延迟实例化。
3.单件模式的类也可以是一般的类,具有一般的数据和方法。
下面是一个单件模式的经典实现:
Public class Singleton(){
//利用一个静态变量来记录Singleton类的唯一实例
Private static Singleton uniqueInstance;
//这里是用到的其他的有用的实例化的变量
//把构造器类设置为私有的,只有自Singleton类内才可以调用构造器
Private Singleton() { }
//用getInstance()方法实例化对象,并返回这个对象的实例
Public static Singleton getInstance(){
If(uniqueInstance==null) {
uniqueInstance=new Singleton();
}
Return uniqueInstance;
}
//这里是其他有用的方法
}
单件模式的多线程之伤
现在我们知道,绝大多数的应用程序都是多线程的,那么我们如果采用上面经典的单例模式的实现化,遇到多线程情况,就会遇到很大的麻烦了
下面我们来处理这种麻烦,处理多线程
在这里只需要我们把getInstance() 变成同步(synchronized)方法即可。
Public class Singleton(){
//利用一个静态变量来记录Singleton类的唯一实例
Private static Singleton uniqueInstance;
//这里是用到的其他的有用的实例化的变量
//把构造器类设置为私有的,只有自Singleton类内才可以调用构造器
Private Singleton() { }
//用getInstance()方法实例化对象,并返回这个对象的实例
Public static synchronized Singleton getInstance(){
if(uniqueInstance==null) {
uniqueInstance=new Singleton();
}
Return uniqueInstance;
}
//这里是其他有用的方法
}
通过增加synchronized 关键字到getInstance()方法中,我们迫使每个线程在进入这个方法之前,要先等候别的线程离开该方法。也就是说,不会有两个线程可以同时进入这个方法。
但这里需要我们注意的是,尽管用这个方式可以很简单的解决了上面的问题,但是这种方法却会降低应用程序的性能。
所以我们考虑一下,能否改善多线程呢?
下面是我们可以采取的几种选择:
1.如果getInstance()的性能对于应用程序不是很关键,就什么也不用去做,直接可以采取上面所说的加上 synchronized 的做法。
2.使用”急切”创建实例,而不用延迟实例化的方法
Public class Singleton{
//在静态初始化器中创建单件,这段代码保证了线程安全。
Private static Singleton uniqueInstace= new Singleton();
Private Singleton () {}
Public static Singleton getInstance() {
Return uniqueInstance;
}
}
采用这个做法,我们依赖JVM 在加载这个类时马上创建此唯一的单件实例。JVM保证在任何线程访问uniqueInstance静态变量之前,一定会创建此实例。
3.用“双重检查加锁”,在getInstance()中减少同步
利用双重检查加锁,首先检查是否实例已经创建了,如果尚未创建,”才”进行同步,这样一来,只有第一次会同步,这正是我们想要的。
Public class Singleton{
//在静态初始化器中创建单件,这段代码保证了线程安全。
Private static Singleton uniqueInstace;
Private Singleton () {}
Public static Singleton getInstance() {
If(uniqueInstance ==null){
Synchronized(Singleton.class) {
If(uniqueInstance ==null){
uniqueInstance =new Singleton();
}
}
}
Return uniqueInstance;
}
}
注意如果使用的是JVM1.2或之前的版本,我们必须建立单间注册表,以免垃圾回收器将单件回收。
总的来说,单件模式相对于其他模式来说类图结构虽然没有那么复杂,但它却扮演着非常重要的角色,在保证应用程序的稳定性和安全性方面起着非常重要的作用。
作者:lhsjohn
网友评论