首页 > 其他 > 详细

设计模式之(三)——单例模式

时间:2015-03-27 22:23:46      阅读:263      评论:0      收藏:0      [点我收藏+]
单例模式:
根据单例模式的设计思想,就是想保证类只有一个实例即只有一个对象。而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源等。
一般出现的场景是:
1、资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如记录系统日志文件,共享配置文件的读取。
2、控制资源的情况下,方便资源之间的互相通信。如线程池,数据库连接池等。
实现方法很多种:
1、饿汉式:
public class SingletonTest {  
    private static SingletonTest instance = new SingletonTest();  
    //私有构造方法  只能通过 公有方法 getInstance 获得实例
    private SingletonTest(){}  
    public static SingletonTest getInstance() {  
        return instance;  
    }  
}  

饿汉式在类加载时静态变量 instance 就进行初始化。资源利用率不好。

2、懒汉式:

public class SingletonTest {  
    private static SingletonTest instance = null;  
    private SingletonTest(){}  
    //synchronized 保证线程同步,线程安全
    public static synchronized SingletonTest getInstance() {  
        if (instance == null) {  
            instance = new SingletonTest();  
        }  
        return instance;  
    }  
}  

懒汉式线程安全,在类加载时并不进行初始化,只是在调用方法getInseance() 时会进行初始化,实现了延迟加载(lazy load)。但是也就是因为只要调用 getInstance() 就会都需要进行 线程锁定判断,进行初始化资源,降低系统的性能,特别是多线程,高并发的状态下。

3、双重校验索锁定(懒汉式的改进):
双重校验是懒汉式的改进,因为当同时有2个进程a,b 调用getInstance(),当a进入 线程锁定,创建对象,b只能等a 执行完,退出来,才能进入进程同步块。但是还是不知道 a 创建对象没有。可能就会出现创建了2个对象。

public class SingletonTest {
    //被volatile修饰的成员变量可以确保多个线程都能够正确处理  
    private volatile static SingletonTest instance = null;  
    private SingletonTest(){}  
    public static synchronized SingletonTest getInstance() {  
       if (instance == null) { //第一次校验 
           synchronized (SingletonTest.class) {  
               if (instance == null) {  //第二次校验
                   instance = new SingletonTest();  
               }  
           }  
        } 
    } 
}  

这样还是有一个问题,就是使用volatile,由于volatile关键字会屏蔽Java虚拟机所做的一些代码的优化,可能会降低系统运行的效率。

4、静态内部类:
静态内部类是一个更好的实现方式,通过内部类创建对象,外部类进行返回。

public class SingletonTest {  
    private static class HolderSingleton {  
        private static final SingletonTest INSTANCE = new SingletonTest();  
    }  
    private Singleton (){}  
    public static final SingletonTest getInstance() {  
        return HolderSingleton .INSTANCE;  
    }  
}  

类加载时不会实例化,只有调用 内部类的 getInstance() 才会实例化,由于是静态的实例,所以创建的实例是唯一的,而且是线程安全的。
其实这就是 IoDH (Initialization Demand Holder) 技术。既可以实现延迟加载,又可以保证线程安全,不影响系统性能。

5、单个元素枚举类型:

public enum SingletonTest {  
    INSTANCE;  
    public void method() {...}  
} 

其实这是Joshua Bloch(Effective Java作者)的思路,这种方法更加简洁,无偿提供序列化机制,绝对防止多次序列化,即使面对复杂的序列化或反射攻击的时候。只是这只能是针对 java 1.5 以上版本的。 因为 java 1.5 才有枚举enum 新特性。

用 Joshua 的话说“单元素的枚举类型已成为实现 Singleton 的最佳方法。”
这是现在至少我很少见过这么用,以后要尝试下。

以上这些都只是我自己的一些见地,仅代表自己的看法。

设计模式之(三)——单例模式

原文:http://blog.csdn.net/u011845742/article/details/44680397

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!