zoukankan      html  css  js  c++  java
  • 单例模式的五种实现方式

    1.懒汉式

    线程不安全:最基础的实现方式,线程上下文单例,不需要共享给所有线程,也不需要加synchronize之类的锁,以提高性能

    package com.yjc.singleton;
    /**
     * 单例之懒汉式
     * */
    public class LazySingleton {
        //构造私有化
        private LazySingleton()
        {
    
        }
        //类加载的时候不进行初始化
        private  static LazySingleton lazySingleton=null;
    
    
        public  static LazySingleton getLazySingleton(){
            //当调用者需要获取一个对象的时候,首先判断当前的对象是否已经进行过实例化了,
            if (lazySingleton!=null){
                //当多个线程同时进入此处的时候,就无法保证是单例的了,因此这种方式是线程非安全的
                lazySingleton=new LazySingleton();
            }
            return lazySingleton;
        }
    
    }

    2.饿汉式

    类加载的时候进行初始化,典型的以空间换时间,线程是安全的,无法做到延迟加载

    package com.yjc.singleton;
    /**
     * 单例之饿汉式
     * */
    public class HungrySingleton {
        //构造私有化
        private HungrySingleton()
        {
    
        }
        private  static HungrySingleton hungrySingleton=new HungrySingleton(); //类加载的时候直接实例化
    
        public  static  HungrySingleton getHungrySingleton()
        {
            return hungrySingleton;
        }
    }

    3.双重锁懒汉模式(Double Check Lock)

    双重校验是懒汉式的升级版,通过加锁实现了线程安全,并同时具备延迟加载的机制

    package com.yjc.singleton;
    /**
     * 单例之双重校验(懒汉式的线程安全版)
     * */
    public class DoubleCheckSingleton {
        //构造方法私有化
        private  DoubleCheckSingleton()
        {
    
        }
        //volatile用于保证内存可见性,所有线程都能看到共享内存的最新状态
        private  static volatile DoubleCheckSingleton doubleCheckSingleton=null;
        
        public  static  DoubleCheckSingleton getDoubleCheckSingleton(){
            if (doubleCheckSingleton!=null){
                //synchronized保证同时只能有一个线程进行实例化对象
                synchronized (DoubleCheckSingleton.class){
                    if (doubleCheckSingleton!=null){
                        doubleCheckSingleton=new DoubleCheckSingleton();
                    }
                }
            }
                return doubleCheckSingleton;
        }
    
    }

    第一次判断doubleCheckSingleton== null为了避免非必要加锁,当第一次加载时才对实例进行加锁再实例化。这样既可以节约内存空间,又可以保证线程安全

    在JDK1.6及之后volatile可以解决DCL失效问题,volatile确保单例对象每次均在主内存中读取,这样虽然会牺牲一点效率,但也没有太多影响

    4.静态内部类

    静态内部类的优点是:在外部类被加载的时候,内部类并不会被立即加载,内部类没有被加载,单例对象也就没有进行实例化,从而也不会占内存。只有在第一次访问内部类中的属性时才会加载内部类

    并将内部类中的对象进行实例化。这种方法不仅可以确保线程的安全和对象唯一,也延迟了单例对象的实例化

    package com.yjc.singleton;
    /**
     * 单例之静态内部类
     * */
    public class StaticInnerClassSingleton {
    
        //构造私有化
        private  StaticInnerClassSingleton()
        {
    
        }
        //静态内部类,外部类被加载时,内部类不会被加载
        private  static  class StaticInnerClass
        {
            // 静态初始化器,由JVM来保证线程安全
            private  static StaticInnerClassSingleton staticInnerClassSingleton=new StaticInnerClassSingleton();
        }
    
        public  static  StaticInnerClassSingleton getStaticInnerClassSingleton()
        {
            //此时开始加载内部类,并将对象进行实例化
            return StaticInnerClass.staticInnerClassSingleton;
        }
    }

    5.枚举

    枚举的特性:枚举实例不仅是线程安全的,而且在任何情况下它都是一个单例,枚举的属性都是静态常量。

    枚举单例可以自己处理序列化:传统的单例模式的另外一个问题是一旦你实现了serializable接口,他们就不再是单例的了,因为readObject()方法总是返回一个 新的实例对象,就像java中的构造器一样。你可以使用readResolve()方法来避免这种情况

    package com.yjc.singleton;
    
    public class Singleton {
            //私有化构造
            private Singleton() {
            }
    
            public static Singleton getInstance() {
                
                return SingletonEnum.INSTANCE.getInstance();
            }
    
            private enum SingletonEnum {
                INSTANCE;
    
                private Singleton singleton;
    
                // JVM保证这个方法绝对只调用一次
                SingletonEnum() {
                    singleton = new Singleton();
                }
    
                public Singleton getInstance() {
                    return singleton;
                }
            }
    }
  • 相关阅读:
    不足百行代码 实体数组转DataTable通用类
    【翻译】WEB安全设计规范(4.1)
    也为读者说几句(兼为什么要骂烂书译者)
    重用之前应仔细分析问题用错轮子有感
    最长代码有多长:不符[单一职责原则(SRP)]的常见设计
    "千里之堤毁于蚁穴"重点项目不能交付之谜(一)泥淖中的验收测试
    企业快速开发框架基于配置文件
    从面试题看高级软件工程师需要哪些技艺
    面试英语【转】
    测试
  • 原文地址:https://www.cnblogs.com/yjc1605961523/p/12074093.html
Copyright © 2011-2022 走看看