单件设计模式
最近老是在研究设计模式,下面我想跟大家分享一下我心得,首先跟大家分享的是“单件模式”,顾名思义,“单件”就是指一个类的实例在整个系统中只有一个(也就是说只初始化一次)。那么它适用于什么场合呢?
适用场合:在一个系统中,往往一些服务只需要它们在整个系统中存在一个实例,并在系统的任何角落都可以调用它。那么如何才能调用呢?很简单,只要在这个类中暴露一个接口给别人调用就OK了。
好处:1.延迟加载。你只需在你要用到该类时,才加载该类。
遇到的问题:1.多线程之间的安全问题。如果多个线程同时访问该类的话,可能会初始化多个该类的实例。所以我们这边要用java的同步机制(synchronized),来锁住初始化的那部分代码,确保该资源同一时间只能被一个线程访问。其实这样会影响性能的,比如第一次,一个线程占有了资源,在它未释放资源之前,如果有很多线程来访问,那么它们就必须等待。在这里我们可以采用double-checking的方式来提高一下性能。下面我来对照一下代码解释一下。
package com.kevin.test;import java.util.ArrayList;import java.util.List;public class Singleton{private static Singleton instance;private static String flag;// initialize listprivate static List<String> arrayList = new ArrayList<String>();private static final Object lockObject = new Object();private Singleton(String flag){this.flag = flag;// initialize in constructor// arrayList = new ArrayList<String>();}public static Singleton getSingleton(String flag){// double-checkingif(instance == null){synchronized (lockObject) {if(instance == null){instance = new Singleton(flag);}}} // not double-checking//synchronized (lockObject) {//if(instance == null){//instance = new Singleton(flag);//}//}return instance;}}如果采用非double-checking的方式的话,如果第一个线程执行完成,释放了资源(也就是说实例已经初始化完成),但是以后的一个线程来访问时,进入锁后,其他要访问该资源的线程还需要需要等待,其实这时候我们已经知道该类的实例已经不为空了,所以我们采用double-checking的方式,当实例已经创建时,我们则不需要进入同步代码块,直接返回实体给该线程了,这样就大大提高了性能。
注意:单件模式的构造函数一定是私有的,为了不让外部区实例化它。
另外,想跟大家说一点,单件模式里面的该类的属性如果有arraylist,hashmap等等时,可以在声明的时候就初始化,或者在构造函数中初始化,如果你想操作这些集合,你需要保证他们的同步。