2008-01-30
设计模式-单例模式(续)
关键字: 设计模式
在《设计模式-单例模式》这篇文章中对单例模式做了一个简单的介绍,接下来本文主要讨论的是多例模式、多线程、双重检查以及“不完全”单例类。
一、多例模式
所谓多例模式,实际上就是单例模式之自然推广,单例类一般情况下只可以有一个实例,但单例类也可以推广到允许有限个实例,这种模式就是多例模式,它的主要特点:多例类可以有多个实例。
二、多线程
下面这段代码使用了线程同步,可以说是线程安全的,一个类不会出现多个实例。如果没有synchronized同步,则在单线程中是安全的,但是到多线程中就可能会出现多个实例。
三、双重检查
仔细观察一下上面的例子,发现同步只是在m_instance没有被创建之前也就是第一次执行此方法时,明显降低性能。有两种方式可以改善,一就是饿汉式单例模式,另外一种就是双重检查。如下面的代码所示:
但是看了《Java与模式》后才发现这样是不行的,虽然想法是好的!不成立的基本原因在于,在Java 编译器中,LazySingleton 类的初始化与m_instance变量赋值的顺序不可预料。如果一个线程在没有同步化的条件下读取m_instance 引用,并调用这个对象的方法的话,可能会发现对象的初始化过程尚未完成,从而造成崩溃。
但是根据最新的JSR133的java内存模型,如果将引用类型声明为volatile,双重检查模式就可以工作了。如下:
四、不完全单例类
如下面的代码所示,看起来好像是懒汉式单例类,但是细看一下,才发现没有隐藏构造函数。这就是不完全单例类。
一、多例模式
所谓多例模式,实际上就是单例模式之自然推广,单例类一般情况下只可以有一个实例,但单例类也可以推广到允许有限个实例,这种模式就是多例模式,它的主要特点:多例类可以有多个实例。
二、多线程
下面这段代码使用了线程同步,可以说是线程安全的,一个类不会出现多个实例。如果没有synchronized同步,则在单线程中是安全的,但是到多线程中就可能会出现多个实例。
public class LazySingleton
{
private LazySingleton m_instance;
private LazySingleton() { }
//对静态工厂方法使用了同步化,以处理多线程环境 关键字synchronized
synchronized public static LazySingleton getInstance()
{
if (m_instance == null)
{
m_instance = new LazySingleton();
}
return m_instance;
}
}
三、双重检查
仔细观察一下上面的例子,发现同步只是在m_instance没有被创建之前也就是第一次执行此方法时,明显降低性能。有两种方式可以改善,一就是饿汉式单例模式,另外一种就是双重检查。如下面的代码所示:
public class LazySingleton
{
private LazySingleton m_instance;
private LazySingleton() { }
public static LazySingleton getInstance()
{
if (m_instance == null)//first cheak
{
synchronized(this)
{
if (m_instance == null)//second cheak
{
m_instance = new LazySingleton();
}
}
}
return m_instance;
}
}
但是看了《Java与模式》后才发现这样是不行的,虽然想法是好的!不成立的基本原因在于,在Java 编译器中,LazySingleton 类的初始化与m_instance变量赋值的顺序不可预料。如果一个线程在没有同步化的条件下读取m_instance 引用,并调用这个对象的方法的话,可能会发现对象的初始化过程尚未完成,从而造成崩溃。
但是根据最新的JSR133的java内存模型,如果将引用类型声明为volatile,双重检查模式就可以工作了。如下:
public class LazySingleton
{
private volatile LazySingleton m_instance;//将引用类型声明为volatile
private LazySingleton() { }
public static LazySingleton getInstance()
{
if (m_instance == null)//first cheak
{
synchronized(this)
{
if (m_instance == null)//second cheak
{
m_instance = new LazySingleton();
}
}
}
return m_instance;
}
}
四、不完全单例类
如下面的代码所示,看起来好像是懒汉式单例类,但是细看一下,才发现没有隐藏构造函数。这就是不完全单例类。
public class LazySingleton
{
private static LazySingleton
m_instance = null;
/**
* 公开的构造子,外界可以直接实例化
*/
public LazySingleton() { } //注意:这里是public
/**
* 静态工厂方法
* @return 返还LazySingleton 类的惟一实例
*/
synchronized public static LazySingleton getInstance()
{
if (m_instance == null)
{
m_instance = new LazySingleton();
}
return m_instance;
}
}







评论排行榜