设计模式—单例模式

2023-11-03


为什么使用单例模式

单例最有代表就是我们耳熟能详的 windows 任务管理器,无论我们创建多少次,总是打开一个窗口。

  1. 如果打开多个重复的窗口,那就是对资源的浪费,资源是宝贵的。
  2. 多个窗口还要保证一致性,否则谁也不知道谁对谁错。
实现

单例模式又可以分为预加载懒加载。当然我们在生产环境中一般使用较多的是 线程安全+懒加载

预加载
/**
 * 预加载
 */
public class PreloadSingleton {
    public static PreloadSingleton instance = new PreloadSingleton();

    /**
     * 其他的类无法实例化单例类的对象
     */
    private PreloadSingleton(){

    }

    public static PreloadSingleton getInstance(){
        return instance;
    }
}

上面这种写法可以保证线程安全。

但是对象还没有使用时就被创建,很明显这种写法会造成资源浪费。


懒加载
/**
 * 懒加载 单例模式
 */
public class LazyLoadingSingleton {
    private static LazyLoadingSingleton instance = null;

    private LazyLoadingSingleton(){}

    public static LazyLoadingSingleton getInstance() {
        if (instance == null){
            instance = new LazyLoadingSingleton();
        }
        return instance;
    }
}

懒加载显然是不能保证线程安全的,在Java实例化对象会分为三步,JVM为了提高程序执行性能,会对没有依赖关系的代码进行重排序。

  1. 初始化内存空间。
  2. 初始化对象。
  3. 设置instance实例指向刚分配的内存空间。

懒加载+线程安全

synchronized 关键字是我们处理线程安全的一个利器,加载 getInstace() 函数可以保证线程安全。但是,如果要经常的调用 getInstance() 方法,不管有没有初始化实例,都会唤醒和阻塞线程。为了避免线程的上下文切换消耗大量时间,如果对象已经实例化了,我们没有必要再使用 synchronized 加锁,直接返回对象。

synchronized

把锁加在 if (instance == null) 里面,保证instance未实例化的时候才加锁。

/**
 * synchronized + 懒加载
 */
public class SynchronizedSingleton {
    private static SynchronizedSingleton instatce = null;
    private SynchronizedSingleton(){}

    public static synchronized SynchronizedSingleton getInstance(){
        if (instatce == null){
            synchronized (SynchronizedSingleton.class) {
                if (instatce == null) {
                    instatce = new SynchronizedSingleton();
                }
            }
        }
        return instatce;
    }
}


synchronized+volatile

Java 在 new 一个对象是无法保证顺序性的。因此需要另一个关键字Volatile保证对象实例化过程中的顺序性。

/**
 * 单例模式,线程安全  synchronized+volatile
 */
public class Singleton {
    private static volatile Singleton instance = null;

    private Singleton(){}

    public static synchronized Singleton getInstance() {
        if (instance == null){
            synchronized (Singleton.class){
                if (instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式—单例模式 的相关文章

随机推荐

  • 堆排序(C)

    文章目录 堆排序 堆的定义 堆排序 构造大根堆 构造小根堆 实现堆排序 测试代码 算法复杂度 堆排序 堆排序的基本思想 对于一组待排序数据 首先按堆的定义建立初始堆 大根堆或小根堆 取出堆顶元素 最大或最小 将剩余的元素继续调整成新堆 就得
  • FeignClient带文件多对象传参

    生产者 ApiOperation value 切块上传 notes 切块上传 PostMapping uploadChunk public Result uploadChunk HttpServletRequest request Chun
  • C语言计算平均分

    已知某位学生的数学 英语和计算机课程的成绩分别是87分 72分和93分 求该生3门课程的平均成绩 结果按整型输出 输入格式 本题无输入 输出格式 按照下列格式输出结果 math 87 eng 72 comp 93 average 计算所得的
  • windows 重启进程和重启服务脚本

    重启进程 以重启远程粘贴板服务为例 已验证 taskkill F IM rdpclip exe 表示杀死进程 F强制杀死 IM 指定杀死的进程名 start rdpclip exe 启动进程 重启服务 未验证 net stop 服务名 ne
  • 自制JLink-ob-072

    陆陆续续的在网上查了两天资料 发现了三篇很有用的文章 一篇是关于固件的 一篇关于硬件的设计 一篇是教你怎么用usb接口给stm32刷固件 有了这三篇资料 自制一个Jlink ob 应该是没问题的了 下面放上链接 固件篇 http www o
  • 剑指offer——day3

    题目1 替换空格 char replaceSpace char s int i 0 int j 0 int len strlen s int cnt 0 for i 0 i lt len i if s i cnt char ans char
  • Ajax与Axios的区别

    目录 1 Ajax与Axios的区别 2 mvvm模式下更适合这种数据 3 ajax书写形式 4 axios书写形式 5 vue 中使用的 axios 代码 总结 1 Ajax与Axios的区别 Axios axios 是通过promise
  • 【技巧】Markdown 交叉引用

    注意 csdn 不支持 md 的跳转 可以使用 toc 生成目录 1 Markdown 引用同一个文件的某一标题 title title 使用 选中章节 将大写字母改成小写 去掉括号 等特殊字符 空格用 替代 2 Markdown 引用另一
  • spring框架历史漏洞复现

    目录 一 docker 1 启动docker 2 列出容器 3 关闭容器 4 进入docker 二 CVE 2016 4977 原理 1 登陆 2 访问url 3 构造payload 4 测试 5 反弹shell 6 编码后的命令结合poc
  • An ASIC Low Power Primer by J. bhaskar

    原文链接 https www academia edu 33242660 An ASIC Low Power Primer by J bhaskar Vlsi Design Power Electronics VLSI VLSI and C
  • jacoco简单教程

    问题 2023 06 06 10 45 52 974563 jacoco简单教程 答案 Jacoco是一个Java代码覆盖率工具 可以帮助开发人员了解他们的代码被测试的程度 以下是Jacoco的简单教程 添加Jacoco插件 在项目的bui
  • golang类型转换与类型断言

    类型转换在程序设计中都是不可避免的问题 当然有一些语言将这个过程给模糊了 大多数时候开发者并不需要去关注这方面的问题 但是golang中的类型匹配是很严格的 不同的类型之间通常需要手动转换 编译器不会代你去做这个事 我之所以说通常需要手动转
  • AD设置某个焊盘铺铜连接方式

    AD设置某个焊盘铺铜连接方式 在规则中创建个别焊盘铺铜连接方式 目的 PCB布板时 将表贴焊盘与铺铜连接方式设置为花焊盘 十字连接 将螺钉孔与铺铜连接方式设置为全连接 步骤一 所有焊盘与铜皮默认为十字连接 单独设置螺钉孔与铜皮全连接 步骤二
  • MYSQL相关问题解惑

    MYSQL如何查看默认存储引擎 方式1 使用show engines语句查看系统中所有的存储引擎 Support列的值表示某种引擎是否能使用 YES表示可以使用 NO表示不能使用 DEFAULT表示该引擎为当前默认存储引擎 方式2 也可以使
  • Linux基本操作指令

    Linnux课程框架学习 LINUX 初识阶段 常用操作 常用工具 1 Linux 系统编程阶段 1 gt 进程概念 2 gt 进程控制 3 gt 基础IO 4 gt 进程间通信 5 gt 进程信号 6 gt 多线程 2 LINUX 网络编
  • 魔兽怀旧服联盟服务器不稳定,魔兽世界怀旧服转服服务关闭最后一天,联盟部落新的对抗...

    魔兽世界这款经典了十几年的游戏有好多的话题可聊 不过恒古不变的热门话题中 联盟与部落的对抗永不过时 在经典怀旧服暂停转服服务即将到来的前一天 某知名论坛又出现了单边大服中阵营之争的唇枪舌战 具体是什么原因引起的 暂时还没有本服大佬出面解释
  • 最全的雅思8000词汇pdf_雅思剑桥1-14同义词汇总,屠鸭必备!(含剑14)

    剑14真题出来之后很多烤鸭私聊哥说什么时候有剑14的同义词替换啊 这不 哥这就来分享了 一个合格的雅思考生的词汇量要在7000左右 而在雅思考试中关于词汇的运用最重要的一部分是 同义词替换 同义词的考察贯穿了雅思考试听说读写的每一项 Lis
  • 【unity笔记】OnCollision和OnTrigger方法使用的一个误区【2D】

    最近在做2D游戏 所以经常使用到两个检测碰撞的方法 OnCollisionXX 方法或OnTriggerXX方法 两个方法的使用大致相同 传入的参数略有差别 void OnCollisionEnter2D Collision2D colli
  • 博弈论【算法】

    目录 定义 巴什博弈 减法博弈 威佐夫博弈 定义 博弈论主要研究公式化了的激励结构间的相互作用 是研究具有斗争或竞争性质现象的数学理论和方法 博弈论考虑游戏中的个体的预测行为和实际行为 并研究它们的优化策略 如囚徒困境 链接 在算法竞赛中出
  • 设计模式—单例模式

    文章目录 为什么使用单例模式 实现 预加载 懒加载 懒加载 线程安全 synchronized synchronized volatile 为什么使用单例模式 单例最有代表就是我们耳熟能详的 windows 任务管理器 无论我们创建多少次