• 设计模式-单例模式


    返回上一级目录:Java设计模式

    单例模式,所谓单例,就是应用只有一个实例对象,该类具有以下特点:

    1. 构造器私有化,保证只有自己才能通过构造器创建实例对象
    2. 持有实例对象的引用,就是最终提供出去的单例实例
    3. 提供一个方法获取该单例实例

    下面是常用的几种实现:

    1、懒汉式

      这是最简单也最容易想到的一种方式。缺点就是不是线程安全,多个线程环境下可能会生成多个实例对象。

    public class Singleton1 {
    
        private static Singleton1 instance;
    
        /**
         * 构造方法私有化
         */
        private Singleton1() {
    
        }
    
        public static Singleton1 getInstance() {
            if (instance == null) {
                instance = new Singleton1();
            }
    
            return instance;
        }
    }

    2、懒汉式(线程安全)

      鉴于懒汉式的缺点,一个改进的方法就是在对getInstance()加锁,确保同时只有一个线程调用。

    public class Singleton2 {
    
        private static Singleton2 instance;
    
        /**
         * 构造方法私有化
         */
        private Singleton2() {
    
        }
    
        /**
         * 弥补了SimpleSingleton1线程安全问题,但是效率很低,任何时候需要instance只能有一个线程去访问getInstance(),
         * 其实只需要在第一次创建对象时候同步,保证只有一个实例被创建
         *
         * @return
         */
        public static synchronized Singleton2 getInstance() {
            if (instance == null) {
                instance = new Singleton2();
            }
    
            return instance;
        }
    }

    3、双重校验锁

      这种方式能很好的解决了懒汉式线程安全和效率的问题,实际应用中通常推荐使用这种方式。

    public class Singleton3 {
    
        /**
         * volatile是禁止new Singleton3()发生指令重排序
         * instance = new Singleton3()在jvm中做了3件事:1.分配内存,2.调用构造方法初始化成员变量,3.将instance指向分配的内存空间
         * jvm在编译时可能对上面步骤2,3重排序,如果先执行3,这时候instance != null,可能被其他线程拿到一个没有初始化完的对象使用而出错
         */
        private static volatile Singleton3 instance;
    
        private Singleton3() {
    
        }
    
        /**
         * 多个线程进入第一个if,只有一个线程进入同步块创建对象,如果其他线程获得锁进入同步块,不判断instance是否已经被创建,
         * 则有可能会创建多个对象
         *
         * @return
         */
        public static Singleton3 getInstance() {
            if (instance == null) {
                synchronized (Singleton3.class) {
                    if (instance == null) {
                        instance = new Singleton3();
                    }
                }
            }
    
            return instance;
        }
    }

    4、饿汉式

      一开始就初始化好一个静态的实例,在其他调用者需要时直接返回。缺点是创建比较简单,不能依赖其他的参数来创建实例对象。

    public class Singleton4 {
    
        private static Singleton4 instance = new Singleton4();
    
        private Singleton4() {
    
        }
    
        /**
         * 类加载后就被初始化,不能依赖其他参数来创建实例
         *
         * @return
         */
        public static Singleton4 getInstance() {
            return instance;
        }
    }

    5、静态内部类

      静态内部类不会随着外部类加载而加载,当getInstance()被调用时,内部类SingletonHolder被加载,接着其静态属性instance初始化。这样不仅保证了延迟加载,也保证了线程安全,也经常被推荐使用。

    public class Singleton5 {
    
        private Singleton5() {
    
        }
    
        private static class SingletonHolder {
            private static Singleton5 instance = new Singleton5();
        }
    
        /**
         * 使用SingletonHolder时候才会加载内部静态类,所以也是懒汉式,类加载机制又保证了多线程的安全性
         *
         * @return
         */
        public static Singleton5 getInstance() {
            return SingletonHolder.instance;
        }
    }

    返回上一级目录:Java设计模式

  • 相关阅读:
    HP SAN Switch參考文檔地址
    hp,Qlogic,Brocade光纖卡查看方式
    使用nbrbutil工具來處理requested media id is in use, cannot process request
    NBU expired Media,Media ID not found in EMM database
    訪問索引的方法
    Linux光纖卡配置,磁盤掛載,多路徑設置
    Linux 6.5網卡配置
    Oracle ASM
    NBU bplabel命令擦除磁帶數據
    鼠标悬浮显示完整信息
  • 原文地址:https://www.cnblogs.com/zhou-920644981/p/12885479.html
Copyright © 2020-2023  润新知