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

Java面试(五)设计模式

文章目录

  • 单例模式
    • 懒汉式
    • 饿汉式
    • 双检锁/双重校验锁(DCL,即 double-checked locking)
    • 单例模式相关的问题
      • 为什么双检索单例模式中的唯一变量要使用volatile关键字来修饰?
      • 单例模式中的唯一实例为什么要设置为静态的?
  • 待更新

单例模式

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

注意:

  1. 单例类只能有一个实例。
  2. 单例类必须自己创建自己的唯一实例。
  3. 单例类必须给所有其他对象提供这一实例。
  4. 构造函数是私有的。

懒汉式

注意

  1. 是否 Lazy 初始化:是
  2. 是否多线程安全:是
  3. 实现难度:易
public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  
}

饿汉式

  1. 是否 Lazy 初始化:否
  2. 是否多线程安全:是
  3. 实现难度:易
public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    	return instance;  
    }  
}

双检锁/双重校验锁(DCL,即 double-checked locking)

  1. 是否 Lazy 初始化:是
  2. 是否多线程安全:是
  3. 实现难度:较复杂
  4. 描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
            if (singleton == null) {  
                singleton = new Singleton();  
            }  
        }  
    }  
    	return singleton;  
    }  
}

单例模式相关的问题

为什么双检索单例模式中的唯一变量要使用volatile关键字来修饰?


主要是因为 singleton = new Singleton() 并不是一个原子指令,在多线程的环境下可能报错。创建一个对象实例,可以分为三步:

  1. 分配对象内存
  2. 调用构造器方法,执行初始化
  3. 将对象引用赋值给变量。

虚拟机实际运行时,以上指令可能发生重排序。以上代码 2,3 可能发生重排序,但是并不会重排序 1 的顺序。也就是说 1 这个指令都需要先执行,因为 2,3 指令需要依托 1 指令执行结果。


Java 语言规规定了线程执行程序时需要遵守 intra-thread semanticsintra-thread semantics 保证重排序不会改变单线程内的程序执行结果。这个重排序在没有改变单线程程序的执行结果的前提下,可以提高程序的执行性能。

虽然重排序并不影响单线程内的执行结果,但是在多线程的环境就带来一些问题。
在这里插入图片描述

public class Singleton {  
    private static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
            if (singleton == null) {  
                singleton = new Singleton();  
            }  
        }  
    }  
    	return singleton;  
    }  
}

上面错误双重检查锁定的示例代码中,如果线程 1 获取到锁进入创建对象实例,这个时候发生了指令重排序。当线程1 执行到 t3 时刻,线程 2 刚好进入,由于此时对象已经不为 Null,所以线程 2 可以自由访问该对象。然后该对象还未初始化,所以线程 2 访问时将会发生异常。所以需要使用volatile修饰singleton。

原文链接

单例模式中的唯一实例为什么要设置为静态的?

单例模式是为了让类的使用者只会创建出一个类的实例,要想达到这样的目的:

  1. 类的构造方法肯定要对其他类隐藏起来
  2. 自己要创建一个实例供其他类来使用
  3. 要提供一个方法给其他类来访问这个实例

要想访问一个类中的方法有两个方式

  • new一个对应类的对象,在通过对象.方法()的方式来调用成员方法
  • 通过类名.方法名()这样来调用对应的类方法

由于单例模式中为了避免外界直接使用构造方法创建实例对象,将构造方法隐藏了起来。此时第一种方法显然无法实现,只有通过第二种方法来获取实例,所以单例模式中的getInstance()方法必须被定义为类方法,即必须加上static。而根据Java语法的要求,在static的环境中是不允许访问非static的成员变量的

待更新

相关文章:

  • docker的简单操作
  • 工业互联网标识解析的数据安全风险有哪些?
  • 2022年外资EDI证办理流程及要求
  • 内网渗透-【横向移动】PsExec工具远程命令执行横向移动
  • 菜谱查询易语言代码
  • springboot+旅游管理系统 毕业设计-附源码261117
  • 未来十年最赚钱的专业是什么
  • R语言ggplot2可视化:使用ggpubr包的ggerrorplot函数可视化误差线(可视化不同水平均值点以及se标准误差)
  • 【Pytorch】torch.Tensor.view()
  • 1766. 互质树 DFS+桶
  • 【课程作业】西瓜书 机器学习课后习题 : 第十二章
  • 【毕业设计】深度学习手势识别实现 - python OpenCV 机器视觉
  • 【数据结构】队列的顺序实现
  • 数据结构与算法基础(1)-- 绪论 (上)
  • LeetCode 每日一题——687. 最长同值路径
  • @jsonView过滤属性
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • Java Agent 学习笔记
  • JavaScript 奇技淫巧
  • java正则表式的使用
  • js ES6 求数组的交集,并集,还有差集
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • js中forEach回调同异步问题
  • Spring Cloud Feign的两种使用姿势
  • vue:响应原理
  • Vue官网教程学习过程中值得记录的一些事情
  • 闭包--闭包之tab栏切换(四)
  • 工作中总结前端开发流程--vue项目
  • 使用SAX解析XML
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 一个完整Java Web项目背后的密码
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • 湖北分布式智能数据采集方法有哪些?
  • # Panda3d 碰撞检测系统介绍
  • (06)金属布线——为半导体注入生命的连接
  • (6)添加vue-cookie
  • (HAL库版)freeRTOS移植STMF103
  • (Oracle)SQL优化技巧(一):分页查询
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (笔试题)合法字符串
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (理论篇)httpmoudle和httphandler一览
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • **PHP二维数组遍历时同时赋值
  • **PHP分步表单提交思路(分页表单提交)
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞
  • .Mobi域名介绍
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置
  • .NET 反射的使用
  • .NET中两种OCR方式对比
  • [AIGC codze] Kafka 的 rebalance 机制
  • [Android] Android ActivityManager
  • [GN] DP学习笔记板子