详解单例模式(Java语言实现)

1. 概念

保证类只有一个实例,让类自身负责保存它的唯一实例,并且类提供一个访问该实例的方法。

2. 单线程下的单例模式

public class Singleton {private static Singleton instance;private Singleton(){}       //private构造方法,其他类无法访问public static Singleton getInstance(){  //获得类实例的唯一全局访问点if(instance==null){instance = new Singleton();}return instance;}
}

注意构造函数用private修饰,外界无法创建此类实例

3. 多线程下的单例模式

3.1. 双重检验锁实现单例模式(懒汉式)

public class Singleton {private volatile static Singleton instance;private Singleton(){}       //private构造方法,其他类无法访问public static Singleton getInstance(){  //获得类实例的唯一全局访问点if(instance == null){synchronized (Singleton.class){if(instance == null){instance = new Singleton();}}}return instance;}
}

细说单例模式中的双重检查锁 - Decouple

终于搞懂双重检验锁实现单例模式了

Java并发常见面试题总结(中)

  • volatile用于禁止指令重排

instance = new Singleton(); 这段代码其实是分为三步执行:

  1. 为 instance 分配内存空间
  2. 初始化 instance
  3. 将 instance 指向分配的内存地址

但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1->3->2。指令重排在单线程环境下不会出现问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3,此时 T2 调用 getInstance()后发现instance 不为空,因此返回 instance,但此时 instance 还未被初始化。

  • 双重检验主要是为了防止每次其他线程想要访问单例都会被阻塞

如果代码设计成如下:

public class Singleton {private volatile static Singleton instance= null;private Singleton() {};public synchronized static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

这样的话,锁的粒度太大了,多个线程同时调用 getInstance() 方法时,除一个线程之外,剩下所有线程都会被阻塞。但是那些线程都只是想访问一下类的唯一实例,这样也被阻塞了,程序的效率大大降低。

为了让程序的效率不那么低,我们缩小同步代码块的范围:

public class Singleton {private volatile static Singleton instance= null;private Singleton() {};public static Singleton getInstance() {if(instance == null){synchronized (Singleton.class){instance = new Singleton();}}return instance;}
}

那这样行不行呢?答案还是不行。

这是由于假设此刻 instance 为 null,如果A,B两个线程同时判断 instance == null 成立,那么两个线程都会进行锁资源的争夺,如果 A 获取到锁资源,则 B 进行阻塞,待 A 完成实例化操作释放掉锁资源后,B 被唤醒,B仍然可以进行实例化操作,创建新的对象,那么便违背了单例模式只有一个实例对象的原则。

因此,需要在同步代码块中再次添加条件判断才行,这才有了双重检验。

3.2. 饿汉式

饿汉式是指在类加载时就初始化唯一实例,并且将其设置为不可变。

上面的懒汉式是在需要该实例时,才会实例化。

public class Singleton {private static final Singleton instance= new Singleton();private Singleton() {};public static Singleton getInstance() {return instance;}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

XGB-14:DMatrix的文本输入格式

简要描述XGBoost的文本输入格式。然而,对于具有支持的语言环境(如Python或R)的用户,建议使用该生态系统中的数据解析器。例如,可以使用sklearn.datasets.load_svmlight_file()。 基本输入格式 XGBoost目前支持两种文…

生成对抗网络

生成对抗网络 GAN 什么是GAN GAN含义:生成对抗网络(Generative Adversarial Networks),主要做目标判别,应用在图像分类、语义分割、目标检测。 GAN简述:GAN包括生成器Generator(G)、判别模型Discriminat…

【架构之路】糟糕程序员的20个坏习惯,切记要改掉

文章目录 强烈推荐前言:坏习惯:总结:强烈推荐专栏集锦写在最后 强烈推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站:人工智能 前言: 优秀的程序员…

关于电脑一天24小时多少度电电脑的一天用电量计算

随着这几年物价的上涨,一些地区的电价越来越高,而我们经常需要使用电脑,那么一台电脑一天24小时用多少度电呢? 如何计算电脑一天的用电量? 让我们跟随小编来了解更多吧。 1、功耗、主机箱功耗 现在的计算机中&#xf…

DTD、XML阐述、XML的两种文档类型约束和DTD的使用

目录 ​编辑 一、DTD 什么是DTD? 为什么要使用 DTD? 内部 DTD 声明 具有内部 DTD 的 XML 文档 外部 DTD 声明 引用外部 DTD 的 XML 文档 二、XML 什么是XML? XML 不执行任何操作 XML 和 HTML 之间的区别 XML 不使用预定义的标记…

js 面试 什么是WebSockets?HTTP和HTTPS有什么不同?web worker是什么?

概念: webSocket 是一种在客户端和服务端之间建立持久连接的协议,它提供全双工通信通道,是服务器可以主动向客户端推送数据,同时也可以接受客户端发送的数据。 1 webSocket与https区别? 在网络通信中,We…

vue-waterfall2 瀑布流,触底加载更多

监听滚动到底部事件: function isScrollToBottom() {const scrollTop document.documentElement.scrollTop || document.body.scrollTop;const scrollHeight document.documentElement.scrollHeight || document.body.scrollHeight;const clientHeight document…

SVN教程-SVN的基本使用

SVN(Apache Subversion)是一款强大的集中式版本控制系统,它在软件开发项目中扮演着至关重要的角色,用于有效地跟踪、记录和管理代码的演变过程。与分布式系统相比,SVN 的集中式架构使得团队能够更加协同地进行开发&…

如何进行写作的刻意练习

写作从来不可能一蹴而就,而是一件需要我们持续坚持、努力的事情。 人如果没有目标就会迷失方向, 既然需要长期的坚持,就需要我们根据自身情况制定每一阶段的目标。 目标的制定要清晰可达,不能模棱两可,要认证对待。 …

基于springboot+vue的二手手机管理系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

【Vue】插槽-slot

📝个人主页:五敷有你 🔥系列专栏:Vue ⛺️稳中求进,晒太阳 插槽 作用:让组件内部一些 结构 支持 自定义 插槽的分类: 默认插槽。具名插槽。 基础语法 组件内需要定制的结构部分&…

WEB漏洞 逻辑越权之支付数据篡改安全

水平越权 概述:攻击者尝试访问与他拥有相同权限的用户的资源 测试方法:能否通过A用户操作影响到B用户 案例:pikachu-本地水平垂直越权演示-漏洞成因 1)可以看到kobe很多的敏感信息 2)burp抓包,更改user…

Codeforces Round 929 (Div. 3)(A,B,C,D,E,F,G)

这场没考什么算法,比较水,难度也不是很高。比赛链接 硬要说的话E有个 前缀和 加 二分,F是数学BFS,G是个构造 A. Turtle Puzzle: Rearrange and Negate 题意: 给你一个由 n n n 个整数组成的数组 a a a 。您必须对…

Unix Domain Socket 比 localhost(127.0.0.1)更快

当本机的进程间通讯时,使用localhost(127.0.0.1)、本机IP 和 Unix Domain Socket 之间有什么区别以前理解比较模糊,今天看了一篇文章,终于高明白了,就是这篇文章,写的非常好: (65 封…

【ERROR-pip-ubuntu】error: can‘t find Rust compiler

这个错误的关键信息是: error: cant find Rust compiler这表示无法找到 Rust 编译器。 针对这个问题,你可以尝试以下解决方法之一: **安装 Rust 编译器:**根据提示,你可以尝试安装 Rust 编译器。你可以从 Rust 官网&…

vscode安装配置

一、通过Code-Server安装 1.1、脚本安装 curl -fsSL https://code-server.dev/install.sh | sh#!/bin/sh set -eu# code-servers automatic install script. # See https://coder.com/docs/code-server/latest/installusage() {arg0"$0"if [ "$0" sh ];…

uniapp+node.js前后端做帖子模块:获取帖子列表(社区管理平台的小程序)

目录 0前提1.一些准备1.1表帖子表 post帖子评论表 postComment帖子点赞表 postLike 1.2总体思路 2.前端3.后端 👍 点赞,你的认可是我创作的动力! ⭐️ 收藏,你的青睐是我努力的方向! ✏️ 评论,你的意见是…

IOC 和 AOP

IOC 所谓的IOC(inversion of control),就是控制反转的意思。何为控制反转? 在传统的程序设计中,应用程序代码通常控制着对象的创建和管理。例如,一个对象需要依赖其他对象,那么它会直接new出来…

LNMP架构搭建

前言 LNMP架构是一种用于搭建Web服务器环境的解决方案,它由Linux、Nginx、MySQL(或MariaDB)、PHP(或Python或Perl)这四个开源软件组成。这种架构通常用于搭建高性能的网站和Web应用程序。 目录 一、编译安装nginx …

MySQL里的两个“二次”

文章中所有图片均来自网络 一、double write 第一个二次是mysql一个崩溃恢复很重要的特性-重复写入。 doublewrite缓冲区是位于系统表空间中的存储区域,在该区域中,InnoDB会在将页面写入数据文件中的适当位置之前,从InnoDB缓冲池中刷新这些页…