zoukankan      html  css  js  c++  java
  • 计模式之单件模式(单例模式)

    单件模式是最简单的设计模式啦!(窝感觉~~)

    有一些对象我们只需要一个,例如:线程池(threadpool),缓存(cache),充当打印机,显卡等设备的驱动程序的对象。

    这些类对象只能有一个实例,多了会出现一些问题。

    全局变量缺点:必须在一开始就创建对象,浪费资源。

    只创建一个对象的方法:首先将构造函数私有,这样这个类就不会随意的创建了。然后为类创建一个产生实例变量的方法。

    public class MyClass {
        private MyClass() {}
        public static MyClass getIntance() {
            return new MyClass();
        }
    }    

    单件模式的实现:

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

    如果不需要这个实例,它就永远不会被产生,这就是“延迟实例化”(lazy-instantiaze)

    单件模式:确保一个类只有一个实例,并提供一个全局访问点。

    但是在多线程情况下,会产生一些问题,如下图情况:

    呀~~产生了两个对象!

    于是在多线程的时候

    需要把getInstance()函数变成同步方法啦

    public static synchronized Singleton getInstance() {
        if (uniqueSingleton == null) {
            uniqueSingleton = new Singleton();
        }
        return uniqueSingleton;
    }

    但是……同步会降低性能……

    1.如果getInstance()方法的性能对应用程序不是很关键,就这样就可以了。

    2.如果程序总是创建并使用单件实例,或者在创建或运行时方面的负担不太繁重,可以一开始就创建实例。

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

    3.用双重加锁,在getInstance()中减少使用同步

    public class Singleton {
        
        private volatile static Singleton uniqueSingleton;    // volatile关键字确保  当uniqueSingleton被初始化后
                                                              // 多个线程正确的处理uniqueSingleton变量
        
        private Singleton() { }
        
        public static Singleton getInstance() {
            if (uniqueSingleton == null) {                    // 检查实例  如果不存在就进入同步区
                synchronized (Singleton.class) {
                    if (uniqueSingleton == null) {            // 进入区块后  在检查一次  如果仍然是null 才创建实例
                        uniqueSingleton = new Singleton();    // 注意:只有第一次才彻底执行这里的代码
                    }
                }
            }
            return uniqueSingleton;
        }
        
    }

    4. 通过枚举实现单例模式

    通过内部静态enum的方法来实现,因为JVM会保证enum不能被反射并且构造器方法只执行一次。

    public class EnumSingleton {
        private EnumSingleton() {}
        
        public static EnumSingleton getInstance(){
            return Singleton.INSTANCE.getInstance();
        }
        
        private static enum Singleton{
            INSTANCE;
            
            private EnumSingleton singleton;
            //JVM会保证此方法绝对只调用一次
            private Singleton(){
                singleton = new EnumSingleton();
            }
            public EnumSingleton getInstance() {
                return singleton;
            }
        }
    }
  • 相关阅读:
    js动态创建table表格的四种方法和性能测试(转载)
    render用法汇总(转载)
    echarts 解决 X轴与Y轴数据不对应问题;X轴日期显示顺序错误问题
    数组对象按时间字符串排序(转载)
    SQL Server 取日期时间部分(转载)
    iview Table行编辑、单元格编辑(转载)
    使用C#创建Windows服务
    马士兵-synchronized
    小程序登录笔记
    Prometheus+Grafana 的方法监控 Springboot 应用
  • 原文地址:https://www.cnblogs.com/wenruo/p/6533648.html
Copyright © 2011-2022 走看看