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

27.Java中单例模式的实现方式

一、单例模式

  单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。

  单例模式中:

  • 这个类只能有一个实例
  • 这个类必须自己创建自己的唯一实例
  • 这个类必须向外提供访问其唯一实例的方式

二、Java中单例模式的实现方式

  Java中常见的单例模式实现方式有五种:

1.饿汉式(Eager Initialization)

  饿汉式在类加载时就创建单例对象,所以在调用时不需要再创建对象,直接使用即可。这种实现方式比较简单,但在某些情况下可能会造成资源的浪费。

public class SingletonEager {private static final SingletonEager INSTANCE = new SingletonEager();private SingletonEager() {}public static SingletonEager getInstance() {return INSTANCE;}
}
2.懒汉式(Lazy Initialization)

  懒汉式在调用时才创建单例对象,这种实现方式避免了资源浪费,但会有线程安全问题。

public class SingletonLazyUnsafe {private static SingletonLazyUnsafe instance;private SingletonLazyUnsafe() {}public static SingletonLazyUnsafe getInstance() {if (instance == null) {instance = new SingletonLazyUnsafe();}return instance;}
}// 注意:懒汉式在多线程环境下是不安全的

  

3.双重检查锁定(Double-Check Locking)

  双重检查锁定是在懒汉式的基础上加入了双重检查锁机制,可以保证线程安全。

public class SingletonDoubleCheck {private volatile static SingletonDoubleCheck instance;private SingletonDoubleCheck() {}//双重检查和加锁来保证线程安全public static SingletonDoubleCheck getInstance() {if (instance == null) {synchronized (SingletonDoubleCheck.class) {if (instance == null) {instance = new SingletonDoubleCheck();}}}return instance;}
}
4.静态内部类(Static Inner Class)

  静态内部类这个方式是将单例对象作为静态内部类的一个静态变量,这种实现方式既可以保证线程安全,又可以实现懒加载。其实现原理是:外部类加载时,并不会立刻加载内部类,内部类不被加载,就不会去创建实例,只有当getInstance方法被调用时,才会加载内部类去创建实例(而且类加载的过程,在JVM中是被设计成线程安全的),所以既保证线程安全又实现了懒加载。

public class SingletonStaticInner {private SingletonStaticInner() {}private static class SingletonHolder {private static final SingletonStaticInner INSTANCE = new SingletonStaticInner();}public static SingletonStaticInner getInstance() {return SingletonHolder.INSTANCE;}
}

5.枚举(Enumeration)

  枚举是实现单例模式的最佳方式,将单例对象定义为一个枚举类型,这种实现方式可以保证线程安全,同时也可以防止反射、反序列化破坏单例模式。

public enum SingletonEnum {INSTANCE;// 定义方法或属性public void someMethod() {// ...}
}// 使用
SingletonEnum.INSTANCE.someMethod();

注意:除了枚举方式,前面四种方式实现的单例模式都存在反射和反序列化破坏单例的问题

  (在不做额外处理的情况下,通过反射可以突破构造方法的私有化限制,强行创建新的实例。而在反序列化时,可能会生成新的对象实例,而不是保持原有的单例状态。)


相关文章:

27.Java中单例模式的实现方式

一、单例模式 单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。 单例模式中: 这个类只能有一个实例这个类必须自己创建自己的唯一实例这个类必须…...

C#面:当一个线程进入一个对象的方法后,其它线程是否可以进入该对象的方法?

一个线程在访问一个对象的一个synchronized方法时: 另一个线程可以同时访问这个对象的非同步方法。另一个线程不可以同时访问这个对象的普通同步方法。另一个线程可以同时访问这个对象的静态同步方法 ,即static synchronized修饰的方法 。另一个线程不可…...

express框架下后端获取req.body报错undefined

express框架下后端获取req.body报错undefined_express服务器post中data为undefine-CSDN博客 /*** 特殊说明:Express是一个单线程服务器器程序【必须存在指定的顺序调用,否则无法达到预期的效果】*//*** 第一步:创建一个Express实例对象,并且在匹配路由之…...

Element plus 低版本弹窗组件添加拖拽功能

在使用element plus 弹窗组件el-dialog 的时候,由于自己组件库版本过低,所以就会缺失某些功能,比如弹窗组件的可拖拽功能。因为某些原因element plus 组件库又不能升级,所以此时就需要自己为弹窗组件添加拖拽功能。共分为一下四个…...

计算机组成原理易混淆知识点总结(持续更新)

目录 1.机器字长,存储字长与指令字长 2.指令周期,机器周期,时钟周期 3.CPI,IPS,MIPS 4.翻译程序和汇编程序 5.计算机体系结构和计算机组成的区别和联系 6.基准程序执行得越快说明机器的性能越好吗? 1.机器字长,存储字长与指令字长 不同的机器三者…...

【STM32踩坑】HAL固件库版本过高导致烧录后无法运行问题

问题引入 目前STM32CUBEMX已经更新到了6.11版本,对应的固件库也一直在更新; 以STM32F1库为例,目前最新的库对应版本为1.8.5 但是我们会发现,如果直接使用1.8.5版本的固件库生成HAL源码后,烧录是可以烧录,但…...

芯片丝印反查

芯片丝印反查网 - IC芯片丝印,IC芯片代码,IC芯片印字,IC芯片顶标,SMD code,marking code,top mark芯查查-电子信息产业数据引擎 ic/芯片丝印反查网-芯查查...

C语言之指针详解(5)(含有易错笔试题)

文章目录 一、sizeof和strlen的对比1.1 sizeof1.2 strlen1.3 sizeof 和 strlen 的对比 二、数组和指针笔试题2.1 一维数组2.2 字符数组2.3 二维数组 三、指针运算笔试题3.1 题目13.2 题目23.3 题目33.4 题目43.5 题目53.6 题目63.7 题目7 一、sizeof和strlen的对比 有一个很神…...

discuzX2.5的使用心得 札记一

从开始接受php论坛的开发任务,对php感兴趣的我开始迷恋上discuz这个产品了, 像戴志康这样的创新人才,是我们这代人的骄傲和学习的榜样 应该是了解一下,啥事discuzX2.5,百度看一下 discuz x2.5_百度百科 看完百度词条…...

【Python】 探索Django框架的高并发处理能力

基本原理 Django是一个高级的Python Web框架,它鼓励快速开发和干净、实用的设计。Django遵循MVC(模型-视图-控制器)设计模式,提供了一个全栈式的解决方案,使得开发者能够快速构建功能丰富的Web应用。Django的高并发处…...

C-数据结构-平横二叉树

平衡二叉树(Balanced Binary Tree)是一种二叉树,其中任意节点的两棵子树的高度差不超过 1。也可以说是一棵空树或者左右子树高度差不超过 1 的二叉树。 特点和性质 高度平衡:平衡二叉树是一种高度平衡的二叉树,任意节…...

算法训练营day41

动态规划理论基础(主要就是确定动态规划的几个步骤) 题目1:509. 斐波那契数 - 力扣(LeetCode) class Solution { public:int fib(int n) {if(n 0) return 0;if(n 1) return 1;int dp1 0;int dp2 1;int dp3 0;fo…...

cesium开发实例分享

反正 cesium 看到的效果几乎都有...

字符串和字符串函数(1)

前言: 字符串在C语言中比较特别,没有单另的字符串类型,想要初始化字符串必须用字符变量的数组初始化,但是在C语言标准库函数中提供了大量能对字符串进行修改的函数,比如说可以实现字符串的的拷贝,字符串的追…...

基于springboot+vue的班级综合测评管理系统

开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...

蓝海项目揭秘:跨境选品师的崛起与挑战

随着全球化贸易的日益深入和电子商务的蓬勃发展,跨境选品师这一新兴职业逐渐走进人们的视野。跨境选品师,顾名思义,就是专门负责为跨境电商平台挑选和推荐适合海外市场的商品的专业人士。那么,跨境选品师这一职业能否被视为一个蓝…...

酷黑简洁大气体育直播自适应模板赛事直播门户网站源码

源码名称:酷黑简洁大气体育直播自适应模板赛事直播门户网站源码 开发环境:帝国cms 7.5 安装环境:phpmysql 支持PC与手机端同步生成html(多端同步生成插件) 带软件采集,可以挂着自动采集发布,无…...

2024年电工杯高校数学建模竞赛(B题) 建模解析| 大学生平衡膳食食谱的优化设计

问题重述及方法概述 问题1:膳食食谱的营养分析评价及调整 数学方法:线性规划模型、营养素评价模型、比较分析 可视化数据图:营养素含量表、营养素摄入量对比图、营养素缺乏情况图 问题2:基于附件3的日平衡膳食食谱的优化设计 数…...

学习编程对英语要求高吗?

学习编程并不一定需要高深的英语水平。我这里有一套编程入门教程,不仅包含了详细的视频讲解,项目实战。如果你渴望学习编程,不妨点个关注,给个评论222,私信22,我在后台发给你。 虽然一些编程资源和文档可能…...

使用 Django 和 RabbitMQ 构建高效的消息队列系统

文章目录 RabbitMQ 简介Django 中使用 RabbitMQ总结与拓展 在现代的 Web 应用程序开发中,构建一个高效的消息队列系统变得越来越重要。使用消息队列可以帮助我们解耦系统中不同模块的任务,并提高系统的性能和可扩展性。本文将介绍如何结合 Django 和 Rab…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言:多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...