锁定老帖子 主题:java单例模式
精华帖 (0) :: 良好帖 (1) :: 新手帖 (16) :: 隐藏帖 (0)
|
|||
---|---|---|---|
作者 | 正文 | ||
发表时间:2011-01-26
最后修改:2011-01-26
Singleton 是一种创建性模型,它用来确保只产生一个实例,并提供一个访问它的全局访问点.对一些类来说,保证只有一个实例是很重要的,比如有的时候,数据库连接或 Socket 连接要受到一定的限制,必须保持同一时间只能有一个连接的存在.再举个例子,集合中的 set 中不能包含重复的元素,添加到set里的对象必须是唯一的,如果重复的值添加到 set,它只接受一个实例.JDK中正式运用了Singleton模式来实现 set 的这一特性,大家可以查看java.util.Collections里的内部静态类SingletonSet的原代码.其实Singleton是最简单但也是应用最广泛的模式之一,在 JDK 中随处可见.
为了实现 Singleton 模式,我们需要的是一个静态的变量,能够在不创建对象的情况下记忆是否已经产生过实例了.静态变量或静态方法都可以在不产生具体实例的情况下直接调用,这样的变量或方法不会因为类的实例化而有所改变.在图1的结构中可以看到,uniqueInstance 就是这个独立的静态变量,它可以记忆对象是否已经实例化了,在静态方法 Instance 中对这个变量进行判断,若没有实例化过就产生一个新的对象,如果已经实例化了则不再产生新的对象,仍然返回以前产生的实例.
实现 Singleton 模式的办法通常有三种. 一. 用静态方法实现 Singleton 这种方法是使用静态方法来监视实例的创建.为了防止创建一个以上的实例,我们最好把构造器声明为 private. 这样可以防止客户程序员通过除由我们提供的方法之外的任意方式来创建一个实例,如果不把构造器声明为private,编译器就会自作聪明的自动同步一个默认的friendly构造器.这种实现方法是最常见的,也就是图1中结构的标准实现.
singletonTest运行结果是: s1 is the same instance with s2 这证明我们只创建了一个实例. 二. 以静态变量为标志实现 Singleton 在类中嵌入一个静态变量做为标志,每次都在进入构造器的时候进行检查. 问题在于构造器没有返回类型,如果确定创建一个实例成功与否.一个方法是调用一个函数来检查创建是否成功,然后简单的返回一个来自静态变量的值,但是这样 做是不优雅的,而且容易发生错误.比较好的做法是创建一个当创建了一个以上的实例时可以抛出异常的类,这个类仅仅是调用父类方法,好处是用了自己命名的异 常类型,错误信息更加清晰:
singletonTest运行结果是: Creating one instance Creating two instance Only one instance allowed 可以看出,第一个实例顺利创建,第二个实例创建实抛出了我们自定义的异常. 三. 用注册器机制来创建 Singleton 首先用集合中的Hashtable 和Enumeration来实现addItem(Object key, Object value),getItem(Object key), ,removeItem(Object key)等方法实现一个管理器,将key和value一一关联起来,客户程序员创建实例前首先用addItem方法进行注册,再用getItem方法获取 实例.Hashtable中的key是唯一的,从而保证创建的实例是唯一的,具体实现限于篇幅不再细说,在Prototype模型的应用一文中我将会给出 一个实现注册器的代码.用注册器机制来创建 Singleton模式的好处是易于管理,可以同时控制多个不同类型的Singleton 实例.
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|||
返回顶楼 | |||
发表时间:2011-01-27
单例代码如下:
public class Singleton { private static Singleton s=new Singleton(); private Singleton(){}; /** * Class method to access the singleton instance of the class. */ public static Singleton getInstance() { return s; } } 完全不用考虑同步问题 |
|||
返回顶楼 | |||
发表时间:2011-01-27
lyw985 写道
单例代码如下:
public class Singleton { private static Singleton s=new Singleton(); private Singleton(){}; /** * Class method to access the singleton instance of the class. */ public static Singleton getInstance() { return s; } } 完全不用考虑同步问题 正解。楼主的方法线程不安全,需要在方法上加同步,但会严重影响效率。 |
|||
返回顶楼 | |||
发表时间:2011-01-27
my_niuniu 写道
lyw985 写道
单例代码如下:
public class Singleton { private static Singleton s=new Singleton(); private Singleton(){}; /** * Class method to access the singleton instance of the class. */ public static Singleton getInstance() { return s; } } 完全不用考虑同步问题 正解。楼主的方法线程不安全,需要在方法上加同步,但会严重影响效率。 这个方法那你得但愿类加载器是一个。。 |
|||
返回顶楼 | |||
发表时间:2011-01-28
whaosoft 写道
my_niuniu 写道
lyw985 写道
单例代码如下:
public class Singleton { private static Singleton s=new Singleton(); private Singleton(){}; /** * Class method to access the singleton instance of the class. */ public static Singleton getInstance() { return s; } } 完全不用考虑同步问题 正解。楼主的方法线程不安全,需要在方法上加同步,但会严重影响效率。 这个方法那你得但愿类加载器是一个。。
95%都是一个,蛋疼才去加几个。 |
|||
返回顶楼 | |||
发表时间:2011-01-28
my_niuniu 写道
lyw985 写道
单例代码如下:
public class Singleton { private static Singleton s=new Singleton(); private Singleton(){}; /** * Class method to access the singleton instance of the class. */ public static Singleton getInstance() { return s; } } 完全不用考虑同步问题 正解。楼主的方法线程不安全,需要在方法上加同步,但会严重影响效率。
|
|||
返回顶楼 | |||
发表时间:2011-01-28
public class Singleton { private volatile static Singleton singleton; private Singleton(){ } public static Singleton getInstance(){ // 双重检查加锁 if(singleton==null){ synchronized(Singleton.class){ // 延迟实例化,需要时才创建 if(singleton==null) singleton = new Singleton(); } } return singleton; } } |
|||
返回顶楼 | |||
发表时间:2011-01-28
加个final吧
|
|||
返回顶楼 | |||
发表时间:2011-01-28
最后修改:2011-01-28
daxiong294 写道
my_niuniu 写道
lyw985 写道
单例代码如下:
public class Singleton { private static Singleton s=new Singleton(); private Singleton(){}; /** * Class method to access the singleton instance of the class. */ public static Singleton getInstance() { return s; } } 完全不用考虑同步问题 正解。楼主的方法线程不安全,需要在方法上加同步,但会严重影响效率。
单例模式最佳写法(没有线程安全问题): public class Singleton { private static class SingletonHolder{ final static Singleton instance= new Singleton (); } private Singleton(){}; public static Singleton getInstance() { return SingletonHolder.instance; } }
JVM加载类不会产生线程安全问题,即两个线程同时去加载这个类,也会按顺序加载,因此会保存SingletonHolder实例的唯一性 |
|||
返回顶楼 | |||
发表时间:2011-01-28
Crusader 写道 public class Singleton { private volatile static Singleton singleton; private Singleton(){ } public static Singleton getInstance(){ // 双重检查加锁 if(singleton==null){ synchronized(Singleton.class){ // 延迟实例化,需要时才创建 if(singleton==null) singleton = new Singleton(); } } return singleton; } } 好像有几篇文章论述了java中DCL不可实现 |
|||
返回顶楼 | |||