单例模式之懒汉式

文章目录

  • 单例模式(懒汉式)
    • 代码
      • 懒汉式(线程不安全)
      • 懒汉式(线程安全,加锁)
      • 双重检查锁(线程安全,推荐)

单例模式(懒汉式)

懒汉式是符合懒加载的模式,但是会存在线程并发的问题发生,所以还需要一种解决线程并发的机制,比如:加锁等

单例模式懒汉式主要的构成是如下

  • 单例类
  • 私有化构造函数(防止实例化)
  • 私有化变量
  • 公共静态获得实例的方法(在调用这个方法的时候才进行实例化)
  • 解决线程并发的机制

代码

懒汉式(线程不安全)

package singleton.type3;

/**
 *
 *
 * @author: Hui
 **/
public class SingletonTest3 {
    
    public static void main(String[] args) {
          Singleton singleton =   Singleton.getInstance();
          Singleton singleton1 =   Singleton.getInstance();
        System.out.println(singleton == singleton1);
        System.out.println(singleton.hashCode());
        System.out.println(singleton1.hashCode());
    }
}

class Singleton{
    
    //1.构造器私有化
    private Singleton(){}
    
    //2.静态实例私有化
    private static Singleton singleton;

    //3.提供实例的静态方法
    public static Singleton getInstance(){
        if (singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
}

以上方法虽然实现了懒加载,但是线程不安全,在实际开发情况下不能使用。

因为以上代码会出现线程不安全的情况,那么我们如何保证线程安全呢?最简单的就是加锁,在提供实例的静态方法中加锁,就可以保证线程安全了。

懒汉式(线程安全,加锁)

package singleton.type4;
/**
 * @author: Hui
 **/
public class SingletonTest4 {

    public static void main(String[] args) {
        System.out.println("线程安全,加锁");
        Singleton singleton = Singleton.getInstance();
        Singleton singleton1 = Singleton.getInstance();
        System.out.println(singleton == singleton1);
        System.out.println(singleton.hashCode());
        System.out.println(singleton1.hashCode());
    }
}

class Singleton {

    //1.构造器私有化
    private Singleton() {
    }

    //2.静态实例私有化
    private static Singleton singleton;

    //3.提供实例的静态方法
    public static synchronized Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

虽然解决了线程安全问题,但是性能太差了,每一次调用实例都需要进入同步方法,其实我们创建实例的时候保持同步就可以了。这个方法因为性能比较差,开发过程中不建议使用。

那上述锁的是一个方法,我们可不可以将锁的颗度降低,锁住一个代码块呢?

代码如下

  //3.提供实例的静态方法
    public static synchronized Singleton getInstance() {
        if (singleton == null) {
            
            synchronized(Singleton){
                 singleton = new Singleton();
            }
        }
        return singleton;
    }

像以上方法是不是就实现了提高性能呢?是的,但是也出现了线程不安全的问题,比如有多个线程进入 if (singleton == null) 那么是不是会有多个线程进行创建对象。所以为了减少颗粒度又要保证线程安全,我们可以使用双层检查锁来完成!!!

  //3.提供实例的静态方法
    public static synchronized Singleton getInstance() {
        if (singleton == null) {
            
            synchronized(Singleton.class){
     			if (singleton == null){
                    singleton = new Singleton();
                } 
            }
        }
        return singleton;
    }

我们只需要在加锁的代码块中再进行一次空判断,就可以很好的解决并发问题了,当一个线程进入的时候,先判断是否为空,为空才创建对象,不为空直接返回。

双重检查锁很好的解决线程不安全问题,并且达到性能的提升。

在实际开发中推荐使用

双重检查锁(线程安全,推荐)

package singleton.type5;

/**
 * @author: Hui
 **/
public class SingletonTest5 {
    public static void main(String[] args) {
        System.out.println("双重检查锁,推荐使用");
        Singleton singleton = Singleton.getInstance();
        Singleton singleton1 = Singleton.getInstance();
        System.out.println(singleton == singleton1);
        System.out.println(singleton.hashCode());
        System.out.println(singleton1.hashCode());
    }
}

class Singleton {

    //1.私有化构造器
    private Singleton() {
    }

    //2.声明静态变量,volatile 保证内存的可见性
    private static volatile Singleton instance;

    public static Singleton getInstance() {

        if (instance == null) {
            synchronized (Singleton.class) {
                //双重检查锁
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }

        return instance;
    }

}

注意变量一定要使用 volatile 修饰,保证变量内存修改时的可见性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/778519.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

推荐好玩的工具之OhMyPosh使用

解除禁止脚本 Set-ExecutionPolicy RemoteSigned 下载Oh My Posh winget install oh-my-posh 或者 Install-Module oh-my-posh -Scope AllUsers 下载Git提示 Install-Module posh-git -Scope CurrentUser 或者 Install-Module posh-git -Scope AllUser 下载命令提示 Install-Mo…

云端AI大模型群体智慧后台架构思考

1 大模型的调研 1.1 主流的大模型 openai-chatgpt 阿里巴巴-通义千问 一个专门响应人类指令的大模型。我是效率助手,也是点子生成机,我服务于人类,致力于让生活更美好。 百度-文心一言(千帆大模型) 文心一言"…

【Linux】进程创建和终止 | slab分配器

进程创建 fork 1.fork 之后发生了什么 将给子进程分配新的内存块和内核数据结构(形成了新的页表映射)将父进程部分数据结构内容拷贝至子进程添加子进程到系统进程列表当中fork 返回,开始调度器调度 这样就可以回答之前返回两个值&#xff1f…

线程池理解及7个参数

定义理解 线程池其实是一种池化的技术实现,池化技术的核心思想就是实现资源的复用,避免资源的重复创建和销毁带来的性能开销。线程池可以管理一堆线程,让线程执行完任务之后不进行销毁,而是继续去处理其它线程已经提交的任务。 …

web缓存代理服务器

一、web缓存代理 web代理的工作机制 代理服务器是一个位于客户端和原始(资源)服务器之间的服务器,为了从原始服务器取得内容,客户端向代理服务器发送一个请求,并指定目标原始服务器,然后代理服务器向原始…

【IT领域新生必看】 Java编程中的重载(Overloading):初学者轻松掌握的全方位指南

文章目录 引言什么是方法重载(Overloading)?方法重载的基本示例 方法重载的规则1. 参数列表必须不同示例: 2. 返回类型可以相同也可以不同示例: 3. 访问修饰符可以相同也可以不同示例: 4. 可以抛出不同的异…

【踩坑】解决undetected-chromedriver报错cannot connect to-chrome

转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~ 网上方法都试了,什么指定version_main、添加option等。 最终,放弃,直接换selenium自己的吧: from web…

【论文解读】LivePortrait:具有拼接和重定向控制的高效肖像动画

📜 文献卡 英文题目: LivePortrait: Efficient Portrait Animation with Stitching and Retargeting Control;作者: Jianzhu Guo; Dingyun Zhang; Xiaoqiang Liu; Zhizhou Zhong; Yuan Zhang; Pengfei Wan; Di ZhangDOI: 10.48550/arXiv.2407.03168摘要翻译: *旨在…

IDEA配Git

目录 前言 1.创建Git仓库,获得可提交渠道 2.选择本地提交的项目名 3.配置远程仓库的地址 4.新增远程仓库地址 5.开始进行commit操作 6.push由于邮箱问题被拒绝的解决方法: 后记 前言 以下操作都是基于你已经下载了Git的前提下进行的&#xff0c…

基于机器学习(支持向量机,孤立森林,鲁棒协方差与层次聚类)的机械振动信号异常检测算法(MATLAB 2021B)

机械设备异常检测方法流程一般如下所示。 首先利用传感器采集机械运行过程中的状态信息,包括,振动、声音、压力、温度等。然后采用合适的信号处理技术对采集到机械信号进行分析处理,提取能够准确反映机械运行状态的特征。最后采用合理的异常决…

算法系列--分治排序|再谈快速排序|快速排序的优化|快速选择算法

前言:本文就前期学习快速排序算法的一些疑惑点进行详细解答,并且给出基础快速排序算法的优化版本 一.再谈快速排序 快速排序算法的核心是分治思想,分治策略分为以下三步: 分解:将原问题分解为若干相似,规模较小的子问题解决:如果子问题规模较小,直接解决;否则递归解决子问题合…

Debezium报错处理系列之第110篇: ERROR Error during binlog processing.Access denied

Debezium报错处理系列之第110篇:ERROR Error during binlog processing. Last offset stored = null, binlog reader near position = /4 Access denied; you need at least one of the REPLICATION SLAVE privilege for this operation 一、完整报错二、错误原因三、解决方法…

智能化客户服务:提升效率与体验的新模式

在数字化浪潮的推动下,客户服务领域正经历着一场深刻的变革。智能化客户服务的兴起,不仅重塑了企业与客户之间的互动方式,更在提升服务效率与增强客户体验方面展现出了巨大潜力。本文将深入探讨智能化客户服务的新模式,分析其如何…

Error in onLoad hook: “SyntaxError: Unexpected token u in JSON at position 0“

1.接收页面报错 Error in onLoad hook: "SyntaxError: Unexpected token u in JSON at position 0" Unexpected token u in JSON at position 0 at JSON.parse (<anonymous>) 2.发送页面 &#xff0c;JSON.stringify(item) &#xff0c;将对象转换为 JSO…

InspireFace-商用级的跨平台开源人脸分析SDK

InspireFace-商用级的跨平台开源人脸分析SDK InspireFaceSDK是由insightface开发的⼀款⼈脸识别软件开发⼯具包&#xff08;SDK&#xff09;。它提供了⼀系列功能&#xff0c;可以满⾜各种应⽤场景下的⼈脸识别需求&#xff0c;包括但不限于闸机、⼈脸⻔禁、⼈脸验证等。 该S…

运维锅总详解CPU

本文从CPU简介、衡量CPU性能指标、单核及多核CPU工作流程、如何平衡 CPU 性能和防止CPU过载、为什么计算密集型任务要选择高频率CPU、超线程技术、CPU历史演进及摩尔定律等方面对CPU进行详细分析。希望对您有所帮助&#xff01; 一、CPU简介 CPU&#xff08;中央处理器&#…

2024年马蹄杯专科组第三场初赛 解题报告 | 珂学家

前言 题解 VP了这场比赛&#xff0c;整体还是偏简单&#xff0c;最难的题是数论相关&#xff0c;算一道思维题。 也看了赛时榜单&#xff0c;除了数论&#xff0c;大模拟和图论题也是拦路虎。 打工人 有趣的一道数学题&#xff0c;有点绕 很像数列和 ∑ i 1 i n i n ∗ …

14-20 Vision Transformer用AI的画笔描绘新世界

概述 毫无疑问,目前最受关注且不断发展的最重要的主题之一是使用人工智能生成图像、视频和文本。大型语言模型 (LLM) 已展示出其在文本生成方面的卓越能力。它们在文本生成方面的许多问题已得到解决。然而,LLM 面临的一个主要挑战是它们有时会产生幻觉反应。 最近推出的新模…

06-6.4.5 关键路径

&#x1f44b; Hi, I’m Beast Cheng &#x1f440; I’m interested in photography, hiking, landscape… &#x1f331; I’m currently learning python, javascript, kotlin… &#x1f4eb; How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以…

Apispec,一个用于生成 OpenAPI(Swagger)规范的 Python 库

目录 01什么是 Apispec&#xff1f; 为什么选择 Apispec&#xff1f; 安装与配置 02Apispec 的基本用法 生成简单的 API 文档 1、创建 Apispec 实例 2、定义 API 路由和视图 3、添加路径到 Apispec 集成 Flask 和 Apispec 1、安装…