zoukankan      html  css  js  c++  java
  • 设计模式-单例模式

    返回上一级目录: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设计模式

  • 相关阅读:
    快速查看表结构(zml)
    康尼机电的发送邮件的功能2
    康尼机电的发送邮件的功能1
    8.2文件控制总览只循环了第一行
    ClientScript.RegisterStartupScript
    康尼机电的委托协议中的点击操作显示标签卡的功能
    1020 Tree Traversals (25 分)
    1017 Queueing at Bank (我自己写的模拟时间的版本)
    1016 Phone Bills ( vector的使用)
    1015 Reversible Primes
  • 原文地址:https://www.cnblogs.com/zhou-920644981/p/12885479.html
Copyright © 2011-2022 走看看