单列模式

2017-07-03  本文已影响0人  huaerlala
一:单列模式的定义

确保某个类只有一个实例。

二:线程安全

说起单列模式,不得不提线程安全,那么什么是线程安全?我们通过几种方式来说说

1.多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。就是线程安全的。

2.你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

3.一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,就是线程安全的。

三:单列模式的几种写法
1:恶汉单列

优点:写法比较简单,在类装载的时候就完成实例化。避免了线程同步问题,天生线程安全。

缺点:类装载的时候就完成实例化,一定程度上会造成资源的浪费。

public class Singleton {

    private static final Singleton INSTANCE=new Singleton();

    private Singleton(){
    }

    public static Singleton getInstance(){
        return INSTANCE;
    }
}
2:懒汉单列

优点:只有使用时,才被实例化。

缺点:效率低,第一次加载需要实例化,反应稍慢。每次调用getInstance方法都会进行同步,消耗不必要的资源。

public class Singleton {

    private static Singleton instance;

    private Singleton(){

    }

    public static synchronized Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}
3:双重检查单列

优点:资源利用率高,效率高。

缺点:第一次加载时反应稍慢。某些情况下失效。

public class Singleton {

    private static Singleton instance;

    private Singleton(){

    }

    public static Singleton getInstance(){
        if(instance == null){
            synchronized (Singleton.class){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
4:静态内部类单列(推荐使用)

优点:保证了线程安全,资源利用率高,效率高。

public class Singleton {

    private static Singleton instance;

    private Singleton() {

    }

    public static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}
5:枚举单列(推荐使用)

优点:写法简单,任何情况下都是一个单列。前面几种方法会在反序列化的时候,重新创建对象。
缺点:实例化一个单例类的时候,必须要记住使用相应的获取对象的方法。并且枚举在SDK1.5中才添加。

public enum SingletonEnum {

    INSTANCE;
    public void doSomething() {

    }
}
五:其他方式

除了以上方式,还可以使用容器形式实现单列

public class SingletonManager {

    private static Map<String, Object> objMap = new HashMap<>();

    private SingletonManager() {

    }

    public static void putObject(String key, String instance){
        if(!objMap.containsKey(key)){
            objMap.put(key, instance);
        }
    }

    public static Object getObject(String key){
        return objMap.get(key);
    }
}
四:备注

不管哪种方式实现,核心原理都是讲构造函数私有化,通过静态方法获取一个唯一的实例,且保证线程安全、防止反序列化导致重新生成实例对象等问题。
实现方式取决项目本身。

另外,附上防止反序列化时重新生成对象方法:

private Object readResolve() throws ObjectStreamException {
    return instance;
}
上一篇 下一篇

猜你喜欢

热点阅读