美文网首页
[Design Pattern]单例模式

[Design Pattern]单例模式

作者: 浩成聊技术 | 来源:发表于2018-07-19 19:25 被阅读12次

    什么是单例模式

    单例模式(Single Pattern),被单例的对象只能有一个实例存在。单例模式的实现方式是,一个类只能返回对象的一个引用和一个获得该唯一实例的方法(此方法必须是静态方法)。

    为什么要使用单例设计模式

    通过单例模式,可以保证系统中只有一个实例,从而在某些特定的场合下达到节约或者控制系统资源

    单例模式分类及其代码实现

    1.饿汉模式

    一开始就创建一个实例。虽然较为简单和常见。但有一个明显的缺点,就是不管有没有调用过获得实例的方法,都会创建一个实例。

    public class Single {
        private static final Single single = new Single();
        private Single(){}
        public static Single getSingle(){
            return single;
        }
    }
    
    2.懒汉模式

    他改进了上述"饿汉模式"的不足之处,调用getSingle() 方法时首先判断实例是否为空,为空才创建实例,并且是调用方法时才创建

    public class Single {
        private static Single single;
        private Single(){}
        public static Single getSingle(){
            if (single == null){
                single =  new Single();
            }
            return single;
        }
    }
    
    3.线程安全的懒汉模式

    懒汉模式也存在问题。那就是如果有多个线程并行调用getSingle() 方法的时候,还是会创建多个实例,那单例子模式就失效了。所以在此基础上设置线程同步(关键子synchonized)。synchronized的作用就是保证在同一时刻最多只有一个线程运行,这样就避免了多线程带来的问题 。

    public class Single {
        private static Single single;
        private Single(){}
        public static synchronized Single getSingle(){
            if (single == null){
                single =  new Single();
            }
            return single;
        }
    }
    
    4.双重检验锁

    上述解决方法,也不是完美的。每次调用getSingle()时都要进行线程同步,考虑一下这种情况,single对象已经创建了,本来直接返回对象使用即可,但却又要进行线程同步。
    于是在此基础之上,又有了双重检验锁的方法

    public class Single {
        private volatile static Single single;
        private Single(){}
        public static Single getSingle(){
            if (single == null){
                synchronized (Single.class){
                    if(single == null){
                        single = new Single();
                    }
                }
            }
            return single;
        }
    }
    
    • 注意

    还需要给实例加一个 volatile 关键字,它的作用就是防止编译器自行优化代码,以保证代码的运行顺序是固定不变的。这涉及到JVM的代码优化机制。

    5.静态内部类

    上述方法不断改进,有点复杂,其实完全可以通过静态内部类来保证线程安全。

    public class Single {
        private static class SingleHoder{
            private static final Single single = new Single();
    } 
        private Single(){}
        public static Single getSingle(){
            return SingleHoder.single;
        }
    }
    

    Single类是私有的,除getSingle()方法*之外没有其他方式可以访问到实例,而且只有调用改方法时才会去创建实例对象。

    6.枚举

    这种方法最为简单。我们可以通过Single.INSANCE来访问实例,并且创建枚举默认就是线程安全的,还可以防止反序列化带来的问题。

    public enum  Single {
        INSTANCE;
        public void whateverMethod(){};
    }
    

    关于作者

    个人博客: http://yhch.xyz

    相关文章

      网友评论

          本文标题:[Design Pattern]单例模式

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