单例模式(Singleton)

定义:确保某一个类只有单一的实例,而且自行实例化,向整个系统提供一个实例,这个类叫单例类,提供全局的访问方法。

单例模式有三个要点:

  1、某个类只能有一个实例

  2、它必须自行创建这个实例

  3、必须自行向整个系统提供这个实例

单例类在消耗资源较大的重型对象中使用较多,如数据库连接的CollectionPool对象,Hibernate中的Configuration对象。Windows上的资源管理器也是由单例模式实现的(只能打开一个资源管理器)。

Singleton的一般实现

 1 Class Singleton{
 2     private static Singleton instance=null;
 3     private Singleton(){}
 4     public static Singleton getInstance(){
 5         if(instance==null){
 6             instance=new Singleton();
 7         }
 8         return instance;
 9     }
10 }
Singleton

  以上代码,在单线程的环境下不会有什么问题,但当多个线程同时访问时(由于单例类一般需要大量初始化工作),可能会导致在没有完全初始化之前,其他线程已经进行if语句判断,并为true。这样的情况会出现多个单例类的实例

线程不安全Singleton的解决方案:

A:EagerSingleton:饿汉单例模式,单例对象的初始化在类加载的时候完成

1 class EagerSingleton{
2     //同理,亦可以使用static代码块实现初始化
3     private static EagerSingleton instance= new EagerSingleton();
4     private EagerSingleton(){}
5     public static EagerSingleton getInstance(){
6         return instance;
7     }
8 }
EagerSingleton

  以上代码,虽然解决了线程安全问题,但是,类加载的时间会延长

B:LazySingleton:懒汉单例模式,利用synchronized对getInstance方法进行线程锁定

 1 class LazySingleton{
 2     private static LazySingleton instance=null;
 3     private LazySingleton(){}
 4     synchronized public static LazySingleton getInstance(){
 5         if(instance==null){
 6             instance=new LazySingleton();
 7         }
 8         return instance;
 9     }
10 }
LazySingleton

  以上代码,可以很好的解决线程安全问题,而且也使用了延迟加载技术,但是每次调用getInstance都需要进行线程锁定判断,大大降低了系统性能

C:Double-Check Locking:双重检查锁定,利用volatile保证多线程下对成员变量的正确处理,在利用双重判断加同步实现LazySingleton

 1 class LazySingleton{
 2     private volatile static LazySingleton instance=null;
 3     private LazySingleton(){}
 4     synchronized public static LazySingleton getInstance(){
 5         if(instance==null){
 6             synchronized(LazySingleton.class){
 7                 if(instance==null){
 8                     instance=new LazySingleton();
 9                 }
10             }
11         }
12         return instance;
13     }
14 }
Double-Check

  以上代码,同样对系统的性能有影响,而且volatile会屏蔽虚拟机的一些代码优化

D:IoDH:使用静态内部类实现延迟加载及线程安全

1 class Singleton{
2     private Singleton(){}
3     private static class Hoder{
4         private final static Singleton instance=new Singleton();
5     }
6     public static Singleton getInstance(){
7         return Holder.instance;
8     }
9 }
IoDH

  以上代码,既可以保证延迟加载,又可以保证线程安全,不影响系统性能,实际上,采用内部类的方法可以将实例化及返回封装成原子操作,这样就完全不需要考虑线程安全问题了,综上所述,这是一种较好的单例模式实现方法

E:单元素的枚举类型:Effective java中提及,实现Singleton的最佳方法

  更加简洁,无偿提供了序列化机制,绝对防止多次实例化,即使是在面对复杂序列化或者反射攻击的时候。虽然这种方法还没有广泛使用。。。所以,笔者不提倡。。。

----------------------------------------------------------------------------------------------------------------------------------------------------------------

不足之处,还望指正

posted @ 2013-10-15 16:12  阿D  阅读(167)  评论(0编辑  收藏  举报