单例模式以及七种实现方式

作者: KaelQ | 来源:发表于2016-10-07 10:16 被阅读1096次

1.定义

  • 一个类只有一个实例,并且只有一个全局获取入口。

2.适用场景

  • 某个实例对象频繁被访问。
  • 某个实例占用的资源较多。

3.实现方式

3.1 懒汉模式(线程不安全)

这样可能会出现线程不同的方法,所以必须对getSingleton方法进行同步。

public class Singleton {
    private static Singleton singleton;//私有静态变量
    private Singleton(){};//私有构造方法
    //全局静态访问入口
    public static Singleton getSingleton(){
        if(singleton==null){
            singleton=new Singleton();
        }
        return singleton;
    }
}

3.2 懒汉模式(线程安全)

public class Singleton {
    private static Singleton singleton;//私有静态变量
    private Singleton(){};//私有构造方法
    //全局静态访问入口
    public static synchronized Singleton getSingleton(){
        if(singleton==null){
            singleton=new Singleton();
        }
        return singleton;
    }
}

这样子线程就安全了,但是消耗了不必要的同步资源,不推荐这样使用。

3.3 饿汉模式(线程安全)

public class Singleton {
    private static Singleton singleton=new Singleton();//私有静态变量
    private Singleton(){};//私有构造方法
    //全局访问入口
    public Singleton getSingleton(){
        return singleton;
    }
}

避免线程安全问题,在声明私有静态变量时,就已经实例化了类,不用考虑线程同步问题。

3.4 DCL模式(Double CheckLock)

public class Singleton {
    private static Singleton singleton;//私有静态内部变量
    private Singleton(){};//私有构造方法
    //全局访问入口
    public static synchronized Singleton getSingleton(){
        if(singleton==null){
            synchronized (Singleton.class){
                if(singleton==null){
                    singleton=new Singleton();
                }
            }
        }
        return singleton;
    }
}

通过两个判断,第一层是避免不必要的同步,第二层判断是否为null。
可能会出现DCL模式失效的情况。
DCL模式失效:
singleton=new Singleton();这句话执行的时候,会进行下列三个过程:

  1. 分配内存。
  2. 初始化构造函数和成员变量。
  3. 将对象指向分配的空间。

由于JMM(Java Memory Model)的规定,可能会出现1-2-3和1-3-2两种情况。
所以,就会出现线程A进行到1-3时,就被线程B取走,然后就出现了错误。这个时候DCL模式就失效了。
Sun官方注意到了这种问题,于是就在JDK1.5之后,具体化了volatile关键字,这时候只用调整一行代码即可。

private volatile static Singleton singleton;

3.5 静态内部类模式

public class Singleton {
    private Singleton(){}
    public static Singleton getSingleton(){
        return SingletonHolder.singleton;
    }
    private static class SingletonHolder{
        private final static Singleton singleton=new Singleton();
    }
}

第一次加载Singleton类不会加载SingletonHolder类,但是调用getSingleton时,才会加载SingletonHolder,才会初始化singleton。即确保了线程安全,又保证了单例对象的唯一性,延迟了单例的实例化。这是最推荐的方式。

3.6 枚举模式

public enum Singleton{
    singleton;
    public void hello(){
        System.out.print("hello");
    }
}

这样很简单,线程时安全的,并且避免了序列化和反射攻击。
除了枚举模式,其他模式在实现了Serializable接口后,反序列化时单例会被破坏。所以要重写readResolve()方法。

private Object readResolve() throws ObjectStreamException {
        return INSTANCE;
    }

3.7 使用容器实现单例模式

public class SingletonManger{
    private static Map<String,Object> objectMap=new HashMap<String,Object>();
    private SingletonManger(){}
    public static void registerService(String key,Object singleton){
        if(!objectMap.containsKey(key)){
            objectMap.put(key,singleton);
        }
    }
    public static Object getObjectService(String key){
        return objectMap.get(key);
    }
}

这样可以将多个单例对象注入到HashMap中,进行统一管理,更加方便快捷。

相关文章

  • iOS 单例实现方式与优缺点

    之前在 实现Singleton 模式——七种实现方式中发现java 的单例有七种实现方式,对里面的懒汉和饿汉模式稍...

  • volicate、单例模式、jvm内存模型联系

    面试中,面试官问起单例模式时,我们是否只乖乖地回答了七种单例模式呢 七种单例模式实现 在单例模式的懒汉模式(线程安...

  • 单例模式以及七种实现方式

    1.定义 一个类只有一个实例,并且只有一个全局获取入口。 2.适用场景 某个实例对象频繁被访问。 某个实例占用的资...

  • 单例模式的常用实现方式

    单例模式属于最常用的设计模式,Java中有很多实现单例模式的方式,各有其优缺点 实现方式对比 单例实现方式线程安全...

  • 设计模式--单例模式

    单例模式概述 单例模式实现方式 为什么要使用单例模式 单例模式实现方式 饿汉式 类加载后就会将对象加载到内存中,保...

  • java单例的几种实现

    以上七种java的单例实现方式。第五种线程安全的单例实现,doublecheck,通过加上volatile,实现真...

  • C++ 单例模式

    本文介绍C++单例模式的集中实现方式,以及利弊 局部静态变量方式 上述代码通过局部静态成员single实现单例类,...

  • kotlin实现单例模式

    1.懒汉式实现单例模式 2.线程安全懒汉式实现单例模式 3.双重校验懒汉式实现单例模式 4.静态内部类方式实现单例模式

  • Python经典面试题21道

    1、Python如何实现单例模式? Python有两种方式可以实现单例模式,下面两个例子使用了不同的方式实现单例模...

  • Python最经典面试题21道,必看!

    1、Python如何实现单例模式? Python有两种方式可以实现单例模式,下面两个例子使用了不同的方式实现单例模...

网友评论

本文标题:单例模式以及七种实现方式

本文链接:https://www.haomeiwen.com/subject/hqgeyttx.html