• 单例模式


    Singleton-单例模式是确定整个系统中至多只有一个类的实例

    第一种:饱汉模式

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

    注:

    (1)private Singleton(){}//私有化类的构造函数,表明这个类无法声明实例对象;

    (2)public static Singleton getInstance()...因为私有化了类的构造函数,所以需要提供一个静态的方法提供类的实例;

    (3)private final static Singleton instance = new Singleton();饱汉模式下,当这个类被加载的时候,new Singleton() 这句话就会被执行,就算是getInstance()没有被调用,类也被初始化了。这种方式不太好的地方就在于,我们只是希望在真正调用getInstance()方法的时候返回类的对象,而不是依赖于类加载器。

    第二种:饥汉模式

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

    注:

    (1)在方法getInstance()加synchronized控制可以帮我们控制线程同步,但是这样每个线程都要排队来获取,而且哪怕是第一个线程已经把对象创建好了也需要逐个获取类对象,会很影响性能。

    (2)改版一,进行Double-Check
    public class Singleton{
        private Singleton(){}
        private static Singleton instance = null;
        public static Singleton getInstance() {
            if(instance == null) {
                synchronized(Singleton.class) {
                    if(instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }

    这样的流程是:

      (1)如果实例创建了,则不需要同步直接返回实例;

      (2)如果不存在,则同步线程进行创建;

      (3)返回。

    但是这样实现的问题就在于:singleton = new Singleton();,因为创建一个类的实例并不是原子操作的,JVM需要:

      (1)分配内存空间;

      (2)进行类的实例化;

      (3)实例对象指向内存地址,返回(只有返回之后,对象instance才不是null,所以这样就还是会存在问题)

    (3)改版二

      将instance声明为volatile,因为被volatile修饰的对象不会在多个线程中同时存在,而是直接从内存中读取。使用volatile关键字声明的变量或对象通常拥有和优化和(或)多线程相关的特殊属性。volatile参考文献

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

     第三种:枚举

    public enum Singleton {
      instance;  
    }

    注:

      默认枚举实例的创建是线程安全的,所以不需要担心线程安全的问题。但是在枚举中的其他任何方法的线程安全由程序员自己负责。还有防止上面的通过反射机制调用私用构造器。

    参考文章:

    单例模式

    深入浅出单实例Singleton设计模式

  • 相关阅读:
    你的DNN站点慢了么?
    SQL锁的应用与描述之二
    自动完成输入框错位
    网页插入flash代码以及技巧
    使用T_SQL脚本创建SQLServer2000后台计划作业任务
    SQL Server实用经典例句之二
    中缀表达式转后缀表达式
    spring cloud config server SSH配置 git private key方式
    vim 技巧一
    jquery 监控文本框键盘事件(回车事件),附常用keycode值。
  • 原文地址:https://www.cnblogs.com/lemon-now/p/5149028.html
Copyright © 2020-2023  润新知