Java 中的单例模式
引言:
在 Java 编程中,单例模式是一种常见的设计模式,它保证一个类只能创建一个实例,并提供一个全局访问点。单例模式在很多场景下都非常有用,比如线程池、日志系统、数据库连接池等。本文将详细介绍 Java 中单例模式的实现方式,并通过示例说明其在实际应用中的应用场景。
一、单例模式的实现方式
在 Java 中,实现单例模式有多种方式,常见的包括:
- 懒汉式(Lazy Initialization):在第一次调用时才创建实例。
- 饿汉式(Eager Initialization):在类加载时就创建实例。
- 双重检查锁(Double-Checked Locking):通过双重检查加锁来确保只有一个实例被创建。
- 静态内部类(Static Inner Class):利用类加载机制保证线程安全并且延迟加载。
下面将分别介绍这些实现方式,并给出相应的示例。
懒汉式单例模式
懒汉式单例模式在第一次调用时才创建实例,示例如下:
public class LazySingleton {private static LazySingleton instance;private LazySingleton() {}public static synchronized LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}
}
饿汉式单例模式
饿汉式单例模式在类加载时就创建实例,示例如下:
public class EagerSingleton {private static final EagerSingleton instance = new EagerSingleton();private EagerSingleton() {}public static EagerSingleton getInstance() {return instance;}
}
双重检查锁单例模式
双重检查锁单例模式通过双重检查加锁来确保只有一个实例被创建,示例如下:
public class DoubleCheckedSingleton {private static volatile DoubleCheckedSingleton instance;private DoubleCheckedSingleton() {}public static DoubleCheckedSingleton getInstance() {if (instance == null) {synchronized (DoubleCheckedSingleton.class) {if (instance == null) {instance = new DoubleCheckedSingleton();}}}return instance;}
}
静态内部类单例模式
静态内部类单例模式利用类加载机制保证线程安全并且延迟加载,示例如下:
public class StaticInnerClassSingleton {private StaticInnerClassSingleton() {}private static class SingletonHolder {private static final StaticInnerClassSingleton instance = new StaticInnerClassSingleton();}public static StaticInnerClassSingleton getInstance() {return SingletonHolder.instance;}
}
二、单例模式的应用场景
单例模式在很多场景下都非常有用,比如:
- 在多线程环境下,需要确保某个类只有一个实例。
- 对象需要被广泛访问,比如日志记录器、数据库连接池等。
- 控制资源的使用,比如线程池、缓存等。
三、各个单例模式的优点和缺点
1. 懒汉式单例模式
优点:
- 延迟加载:在第一次调用
getInstance()方法时才会创建实例,节省了内存资源。 - 线程安全(通过 synchronized 关键字):在多线程环境下也能够正常工作。
缺点:
- 性能低:由于在每次获取实例时都需要加锁,会导致性能下降。
- 可能出现线程安全问题:在多线程环境下,由于加锁的开销较大,可能会出现多个线程同时创建实例的情况。
2. 饿汉式单例模式
优点:
- 线程安全:由于在类加载时就创建实例,所以可以保证线程安全。
缺点:
- 浪费内存:在应用程序启动时就创建实例,可能会造成内存浪费,尤其是在实例很大或者实例化开销很大的情况下。
- 不能实现延迟加载:如果在应用程序启动时就创建实例,而实例的创建又很消耗资源,可能会影响应用程序的启动速度。
3. 双重检查锁单例模式
优点:
- 延迟加载:通过双重检查加锁的方式实现延迟加载,提高了性能。
- 线程安全:在多线程环境下也能够保证只有一个实例被创建。
缺点:
- 实现复杂:需要考虑线程安全、对象创建和性能等多个方面的问题,容易出错。
- 可能存在指令重排序问题:在某些情况下,可能会由于指令重排序而导致获取到未完全初始化的实例。
4. 静态内部类单例模式
优点:
- 延迟加载:通过静态内部类的加载机制实现延迟加载,提高了性能。
- 线程安全:在类加载时就完成了实例化,保证了线程安全。
缺点:
- 可能存在反序列化问题:如果单例类实现了
Serializable接口,在进行反序列化时可能会破坏单例模式。 - 对象创建时机不可控:由于是在类加载时创建实例,因此无法控制实例创建的时机。
总结:
在选择单例模式的实现方式时,需要根据具体的应用场景和需求综合考虑。如果需要延迟加载、并且在多线程环境下保证线程安全,可以选择双重检查锁单例模式或者静态内部类单例模式;如果希望在应用程序启动时就创建实例,并且不考虑性能问题,可以选择饿汉式单例模式;如果需要延迟加载并且希望代码简洁、安全可靠,可以选择静态内部类单例模式。在实际应用中,需要根据具体情况选择合适的单例模式实现方式,以确保程序的正确性和性能。
相关文章:
Java 中的单例模式
引言: 在 Java 编程中,单例模式是一种常见的设计模式,它保证一个类只能创建一个实例,并提供一个全局访问点。单例模式在很多场景下都非常有用,比如线程池、日志系统、数据库连接池等。本文将详细介绍 Java 中单例模式的…...
鸿蒙OS开发实例:【ArkTS类库多线程I/O密集型任务开发】
使用异步并发可以解决单次I/O任务阻塞的问题,但是如果遇到I/O密集型任务,同样会阻塞线程中其它任务的执行,这时需要使用多线程并发能力来进行解决。 I/O密集型任务的性能重点通常不在于CPU的处理能力,而在于I/O操作的速度和效率。…...
OpenStack部署
目录 一、安装环境 1.无网络使用该命令 2.修改主机名 3.配置hosts解析 4.配置本机免密 5.关闭防火墙和SElinux策略 6.关闭NewworkManager 7.修改yum源 7.1下载阿里源 7.2清空并加载缓存yum源 8.安装基本工具 9.系统升级 10.安装OPenStack的yum仓库 11.修改OPenSt…...
Java中的多线程和线程安全问题
线程 线程是操作系统进行调度的最小单位。一个进程至少包含一个主线程,而一个线程可以启动多个子线程。线程之间共享进程的资源,但也有自己的局部变量。多线程程序和普通程序的区别:每个线程都是一个独立的执行流;多个线程之间是…...
java Web会议信息管理系统 用eclipse定制开发mysql数据库BS模式java编程jdbc
一、源码特点 jsp 会议信息管理系统是一套完善的web设计系统,对理解JSP java SERLVET mvc编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发,数据库为Mysql5.0&am…...
lock4j学习记录
一种简单的,支持不同方案的高性能分布式锁 简介 lock4j是一个分布式锁组件,其提供了多种不同的支持以满足不同性能和环境的需求。 立志打造一个简单但富有内涵的分布式锁组件。 特性 简单易用,功能强大,扩展性强。支持redis…...
【C++庖丁解牛】自平衡二叉搜索树--AVL树
🍁你好,我是 RO-BERRY 📗 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油 目录 前言1 AVL树的概念2. AVL…...
ES5和ES6的深拷贝问题
深拷贝我们知道是引用值的一个问题,因为在拷贝的时候,拷贝的是在内存中同一个引用。所以当其中的一个应用值发生改变的时候,其他的同一个引用值也会发生变化。那么针对于这种情况,我们需要进行深度拷贝,这样就可以做到…...
阿里云发送短信配置
依赖 <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.2.1</version> </dependency> <dependency><groupId>org.apache.httpcomponents</groupId&g…...
axios封装,请求取消和重试,请求头公共参数传递
axios本身功能已经很强大了,封装也无需过度,只要能满足自己项目的需求即可。 常规axios封装,只需要设置: 实现请求拦截实现响应拦截常见错误信息处理请求头设置 import axios from axios;// 创建axios实例 const service axios…...
隐私计算实训营学习五:隐语PSI介绍及开发指南
文章目录 一、SPU 实现的PSI介绍1.1 PSI定义和种类1.1.1 PSI定义和种类1.1.2 隐语PSI功能分层 1.2 SPU 实现的PSI介绍1.2.1 半诚实模型1.2.2 PSI实现位置 二、SPU PSI调度架构三、Secretflow PSI开发指南四、隐语PSI后续计划 一、SPU 实现的PSI介绍 1.1 PSI定义和种类 1.1.1 …...
ES的RestClient相关操作
ES的RestClient相关操作 Elasticsearch使用Java操作。 本文仅介绍CURD索引库和文档!!! Elasticsearch基础:https://blog.csdn.net/weixin_46533577/article/details/137207222 Elasticsearch Clients官网:https://ww…...
linux通用命令 ssh命令连接慢问题排查
系列文章目录 文章目录 系列文章目录一、 ssh 连接慢3.1 查找原因3.2 解决方案 一、 ssh 连接慢 最近的 koji 服务器 使用 ssh 连接很慢。 3.1 查找原因 可以通过 ssh -vvv 192.168.0.123 或 time ssh root192.168.0.123 exit 查找原因如下: SERVER的SSHD会去DN…...
7.卷积神经网络与计算机视觉
计算机视觉是一门研究如何使计算机识别图片的学科,也是深度学习的主要应用领域之一。 在众多深度模型中,卷积神经网络“独领风骚”,已经被称为计算机视觉的主要研究根据之一。 一、卷积神经网络的基本思想 卷积神经网络最初由 Yann LeCun&a…...
Linux|如何管理多个Git身份
摘要 关于如何管理不同项目和多个Git身份。 作为一名通用软件开发者,我经常发现自己在处理各种各样的项目,每个项目都有自己的要求和期望。这包括为个人、工作和客户项目管理不同的Git身份。以下是我组织Git仓库以简化这一过程的方法。 目录组织 我将我的…...
力扣---最长回文子串---二维动态规划
二维动态规划思路: 首先,刚做完这道题:力扣---最长有效括号---动态规划,栈-CSDN博客,所以会有一种冲动,设立g[i],表示以第i位为结尾的最长回文子串长度,然后再遍历一遍取最大长度即可…...
(一)kafka实战——kafka源码编译启动
前言 本节内容是关于kafka消息中间键的源码编译,并通过idea工具实现kafka服务器的启动,使用的kafka源码版本是3.6.1,由于kafka源码是通过gradle编译的,以及服务器是通过scala语言实现,我们要预先安装好gradle编译工具…...
Spring Boot 使用 Redis
1,Spring 是如何集成Redis的? 首先我们要使用jar包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><gro…...
火车头通过关键词采集文章的原理
随着互联网信息的爆炸式增长,网站管理员和内容创作者需要不断更新和发布新的文章,以吸引更多的用户和提升网站的排名。而火车头作为一款智能文章采集工具,在这一过程中发挥着重要作用。本文将探讨火车头如何通过关键词采集文章,以…...
Kafka 面试题及参考答案
目录 1. Kafka 的核心特性是什么? 2. Kafka 为什么能够实现高吞吐量? 3. Kafka 的消息丢失是...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...
Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...
Linux-进程间的通信
1、IPC: Inter Process Communication(进程间通信): 由于每个进程在操作系统中有独立的地址空间,它们不能像线程那样直接访问彼此的内存,所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...
Canal环境搭建并实现和ES数据同步
作者:田超凡 日期:2025年6月7日 Canal安装,启动端口11111、8082: 安装canal-deployer服务端: https://github.com/alibaba/canal/releases/1.1.7/canal.deployer-1.1.7.tar.gz cd /opt/homebrew/etc mkdir canal…...
