单列模式

作者: fomin | 来源:发表于2018-09-18 23:20 被阅读17次

    1、什么是单列模式

    单列模式(Singleton)保证一个类仅有一个实例,并提供一个访问的全局访问点,这种类型的设计模式属于创建型模式。在开发中,会经常遇到一个全局使用的类频繁地创建与销毁,这会非常浪费系统的内存资源,而且容易导致错误甚至一定会产生错误,所以我们单例模式所期待的目标或者说使用它的目的,是为了尽可能的节约内存空间,减少无谓的GC消耗,并且使应用可以正常运作。


    结构图

    2、实现方式

    2.1、懒汉模式,线程不安全

    最基本的实现方式,这种实现最大的问题就是不支持多线程。

    public class Singleton {
    
        private static Singleton instance;
    
        private Singleton() {
    
        }
    
        public static Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    

    针对懒汉模式线程不安全的问题,我们自然想到了,在getInstance()方法前加锁,于是就有了第二种实现

    2.2、懒汉模式,线程安全

    能够在多线程中很好的工作,打补丁方式写出来的结构效率很低,多数情况下不需要同步。

    public class Singleton {
    
        private static Singleton instance;
    
        private Singleton() {
    
        }
    
        public static synchronized Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    

    因为加了synchronized为独占排他锁,并发性能差,于是为了解决这个问题又有第三种实现

    2.3、饿汉式

    在类加载的时候,就完成了对象的初始化,类加载保证了他们天生是线程安全的

    public class Singleton {
    
        private static Singleton instance = new Singleton();
    
        private Singleton() {
    
        }
    
        public static Singleton getInstance() {
            return instance;
        }
    }
    

    没有达到Lazy Loading的效果,如果从始至终从未使用过这个实例,则会造成内存的浪费,那如何解决这个问题呢?

    2.4、静态内部类

    Singleton 类被装载了,instance 不一定被初始化,只有在调用的时候才进行加载,达到了类似懒汉模式的效果,而这种方法又是线程安全的。

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

    2.5、枚举

    枚举实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化和线程安全的

    public enum Singleton {
    
        INSTANCE;
    
        public void action() {
    
        }
    }
    调用
    Singleton.INSTANCE.action();
    

    2.6、双重校验锁法

    采用双锁机制,安全且在多线程情况下能保持高性能

    public class Singleton {
    
        private volatile static Singleton singleton;
        
        private Singleton (){}
        public static Singleton getSingleton() {
            if (singleton == null) {
                synchronized (Singleton.class) {
                    if (singleton == null) {
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }
    

    3、总结

    推荐使用3-6的实现方式,当然并不是说1-2不能使用,具体的还需要根据业务场景来使用,例如不需要再多线程使用的可以根据1来实现;需要支持序列化的可以使用5来实现,一般情况下建议使用3来实现

    相关文章

      网友评论

        本文标题:单列模式

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