当前位置: 首页 > news >正文

单例设计模式

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

1、单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例

2、饿汉式单例类

  • 在这个类被加载时,静态变量instance会被初始化,此时类的私有构造子会被调用
  • 饿汉式是典型的空间换时间
public class EagerSingleton {
    private static EagerSingleton instance = new EagerSingleton();
    /**
     * 私有默认构造子
     */
    private EagerSingleton(){}
    /**
     * 静态工厂方法
     */
    public static EagerSingleton getInstance(){
        return instance;
    }
}

3、懒汉式单例类

  • 对静态工厂方法使用了同步化,以处理多线程环境
  • 懒汉式是典型的时间换空间
public class LazySingleton {
    private static LazySingleton instance = null;
    /**
     * 私有默认构造子
     */
    private LazySingleton(){}
    /**
     * 静态工厂方法
     */
    public static synchronized LazySingleton getInstance(){
        if(instance == null){
            instance = new LazySingleton();
        }
        return instance;
    }
}

4、双重检查加锁

  • 既实现线程安全,又能够使性能不受很大的影响
  • 被volatile修饰的变量的值,将不会被本地线程缓存
  • 所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量
  • 由于volatile关键字可能会屏蔽掉虚拟机中一些必要的代码优化,所以运行效率并不是很高
  • 可以使用“双重检查加锁”机制来实现线程安全的单例,但并不建议大量采用,可以根据情况来选用
public class Singleton {
    private volatile static Singleton instance = null;
    private Singleton(){}
    /**
     * 双重锁的原因是,俩线程同时进入if 语句内部,一个获得锁执行,另一个阻塞,
     * 如果不再判断下,一个创建完之后,另一个在创建一个
     */
    public static Singleton getInstance(){
        //先检查实例是否存在,如果不存在才进入下面的同步块
        if(instance == null){
            //同步块,线程安全的创建实例
            synchronized (Singleton.class) {   
                //再次检查实例是否存在,如果不存在才真正的创建实例
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

5、Lazy initialization holder class模式

  • 综合使用了Java的类级内部类和多线程缺省同步锁的知识,很巧妙地同时实现了延迟加载和线程安全
  • 当getInstance方法第一次被调用的时候,它第一次读取SingletonHolder.instance,导致SingletonHolder类得到初始化
public class Singleton {
    
    private Singleton(){}
    /**
     *    类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
     *    没有绑定关系,而且只有被调用到时才会装载,从而实现了延迟加载。
     */
    private static class SingletonHolder{
        /**
         * 静态初始化器,由JVM来保证线程安全
         */
        private static Singleton instance = new Singleton();
    }
    
    public static Singleton getInstance(){
        return SingletonHolder.instance;
    }
}

类级内部类:

  • 有static修饰的成员式内部类。如果没有static修饰的成员式内部类被称为对象级内部类
  • 类级内部类相当于其外部类的static成分,它的对象与外部类对象间不存在依赖关系,因此可直接创建
  • 对象级内部类的实例,是绑定在外部对象实例中的
  • 类级内部类中,可以定义静态的方法,在静态方法中只能够引用外部类中的静态成员方法或者静态成员变量
  • 类级内部类相当于其外部类的成员,只有在第一次被使用的时候才被会装载

多线程缺省同步锁:

  • 在多线程开发中,为了解决并发问题,主要是通过使用synchronized来加互斥锁进行同步控制
  • 在某些情况中,JVM已经隐含地为您执行了同步,这些情况下就不用自己再来进行同步控制

这些情况包括:

  1. 由静态初始化器(在静态字段上或static{}块中的初始化器)初始化数据时
  2. 访问final字段时
  3. 在创建线程之前创建对象时
  4. 线程可以看见它将要处理的对象时

6、单例与枚举

  • 单元素的枚举类型已经成为实现Singleton的最佳方法
  • 使用枚举来实现单实例控制会更加简洁,而且无偿地提供了序列化机制
  • 由JVM从根本上提供保障,绝对防止多次实例化,是更简洁、高效、安全的实现单例的方式
/**
 * 使用枚举的单例模式
 *
 * @see [相关类/方法](可选)
 * @since [产品/模块版本] (可选)
 */
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;
        }
    }
}
  • 枚举实例的创建默认就是线程安全的,你不需要担心双检锁问题
  • JVM会保证enum不能被反射并且构造器方法只执行一次

转载于:https://my.oschina.net/u/3847203/blog/1833648

相关文章:

  • PHP多进程系列笔记(三)
  • Netty基础
  • 探讨.NET Core的未来
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • Mantis 1.3.13报表显示问题
  • SQL Server 与 DSN
  • 关于怎么在手机端实现一个拖拽的操作
  • 每日笔记之2018-06-26之小总结
  • emoji web端处理
  • libvirt-qemu-虚拟机设备热插拔
  • 【刷算法】从上往下打印二叉树
  • 温故之.NET 中的并行并发概念解析
  • 命名实体识别从数据集到算法实现
  • 过滤器的功能实现
  • ps:建立规则选区
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • Meteor的表单提交:Form
  • mongo索引构建
  • node学习系列之简单文件上传
  • VUE es6技巧写法(持续更新中~~~)
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • yii2中session跨域名的问题
  • 包装类对象
  • 编写高质量JavaScript代码之并发
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 对象引论
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 入手阿里云新服务器的部署NODE
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • ​Python 3 新特性:类型注解
  • ​水经微图Web1.5.0版即将上线
  • # 安徽锐锋科技IDMS系统简介
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (1)bark-ml
  • (bean配置类的注解开发)学习Spring的第十三天
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (Matlab)使用竞争神经网络实现数据聚类
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (强烈推荐)移动端音视频从零到上手(上)
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置
  • .NET DataGridView数据绑定说明
  • .Net Remoting常用部署结构
  • .NET 读取 JSON格式的数据
  • .NET 反射 Reflect
  • .NetCore部署微服务(二)
  • .NET教程 - 字符串 编码 正则表达式(String Encoding Regular Express)
  • .NET与java的MVC模式(2):struts2核心工作流程与原理