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

设计模式快速学习(三)单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

优点

1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。

2、避免对资源的多重占用(比如写文件操作)。

缺点

没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

实现方式一:懒汉式(线程不安全)

懒汉式:就是用的时候再进行实例化对象。

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}
复制代码

这种实现方式不支持多线程,因为没有同步锁,多线程下不能正常工作。

实现方式二:懒汉式(线程安全)

public class Singleton {
    private static Singleton instance;

    public static synchronized Singleton getInstance(){
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}
复制代码

可以在多线程环境下使用,但是效率太低。

优点:一个对象初始化一次,节省内存。

缺点:必须用synchronized来维持单例,没效率。

实现方式三:饿汉式(线程安全)

public class Singleton {
    private static Singleton instance = new Singleton();

    public static Singleton getInstance(){
        return instance;
    }
}
复制代码

因为它作为静态资源,所以在类装载时就被实例化

优点:没有加锁,执行效率会提高。

缺点:类加载时就初始化,浪费内存。

实现方式四:双检锁/双重校验锁DCL(线程安全)

public class Singleton {
    private static Singleton instance;

    public static Singleton getInstance(){
        if (instance == null){
            synchronized (Singleton.class){
                if (instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
复制代码

采用双锁机制,安全且在多线程情况下能保持高性能。详细了解请点击:Java并发编程 -- 单例模式线程安全问题

实现方式五:登记式/静态内部类(线程安全)

public class Singleton {
    private static Singleton instance;

    private static class SingletonHandler{
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance(){
        return SingletonHandler.INSTANCE;
    }
}
复制代码

这种方式可以说是恶汉式的变通版,SingletonHandler没有被主动使用的情况下是不会实例化Singleton对象的,所以这样做,既能达到lazy式的加载,又能保证线程安全。

实现方式六:枚举类(线程安全)

public enum  Singleton {
    INSTANCE;
    public void myMethod() {
        System.out.println("enum instance test");
    }
}
复制代码

它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。

测试:

public class Main {
    public static void main(String[] args) {
        Singleton singleton = Singleton.INSTANCE;
        singleton.myMethod();
    }
}
复制代码
enum instance test
复制代码

总结

不建议使用第 1 种和第 2 种懒汉方式,建议使用第 3 种饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用第 5 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。

相关文章:

  • hadoop实操篇:hadoop基础教程汇总
  • python2.7用socks和socket设置代理
  • 关于VS2017编译UE4项目,输出窗口有乱码的解决方案
  • Java全栈程序员之01:做个Linux下的程序猿
  • 如何靠谱地查到Tomcat的版本
  • Maven根据pom文件中的Profile标签动态配置编译选项
  • openlayers+geoserver+wms实现空间查询,属性查询
  • 关于 HandlerMethodArgumentResolver 类 以及 WebArgumentResolver 类 自定义解析参数
  • vue.js有什么用,是用来做什么的(整理)
  • Redis字符串类型内部编码剖析
  • HAPkendoUI的Excle导出
  • js 和 css动画
  • [IOI2007 D1T1]Miners 矿工配餐
  • 10.监视SQL Server性能
  • QEMU增量镜像制作
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • [译] React v16.8: 含有Hooks的版本
  • cookie和session
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • exif信息对照
  • export和import的用法总结
  • Hibernate最全面试题
  • IE报vuex requires a Promise polyfill in this browser问题解决
  • java第三方包学习之lombok
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • JS笔记四:作用域、变量(函数)提升
  • Netty源码解析1-Buffer
  • PaddlePaddle-GitHub的正确打开姿势
  • 番外篇1:在Windows环境下安装JDK
  • 关于Java中分层中遇到的一些问题
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • zabbix3.2监控linux磁盘IO
  • 进程与线程(三)——进程/线程间通信
  • 如何通过报表单元格右键控制报表跳转到不同链接地址 ...
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • ​水经微图Web1.5.0版即将上线
  • #100天计划# 2013年9月29日
  • #每日一题合集#牛客JZ23-JZ33
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • ***测试-HTTP方法
  • ..回顾17,展望18
  • .NET MVC第五章、模型绑定获取表单数据
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .NET中 MVC 工厂模式浅析
  • @cacheable 是否缓存成功_让我们来学习学习SpringCache分布式缓存,为什么用?
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • [ 数据结构 - C++] AVL树原理及实现
  • [ABC294Ex] K-Coloring