Java 单例模式实现方式

Java 单例模式实现方式

  单例模式是确保一个类只有一个实例,并提供一个全局访问点的设计模式。以下是 Java 中实现单例模式的几种常见方式:

1. 饿汉式(Eager Initialization)

public class EagerSingleton {// 类加载时就初始化private static final EagerSingleton INSTANCE = new EagerSingleton();// 私有构造函数private EagerSingleton() {}public static EagerSingleton getInstance() {return INSTANCE;}
}

特点

  • 线程安全(由JVM类加载机制保证)
  • 简单直接
  • 可能造成资源浪费(即使不用也会创建实例)

2. 懒汉式(Lazy Initialization,非线程安全)

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

问题

  • 非线程安全,多线程环境下可能创建多个实例

3. 懒汉式(同步方法,线程安全但效率低)

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

特点

  • 线程安全
  • 每次获取实例都需要同步,性能较差

4. 双重检查锁定(Double-Checked Locking)

public class DCLSingleton {// 使用volatile禁止指令重排序private static volatile DCLSingleton instance;private DCLSingleton() {}public static DCLSingleton getInstance() {if (instance == null) { // 第一次检查synchronized (DCLSingleton.class) {if (instance == null) { // 第二次检查instance = new DCLSingleton();}}}return instance;}
}

特点

  • 线程安全
  • 只有第一次创建时需要同步
  • Java 5+ 需要配合 volatile 使用

5. 静态内部类(Holder模式,推荐)

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

优点

  • 线程安全(由JVM类加载机制保证)
  • 懒加载(只有调用getInstance()时才加载内部类)
  • 无同步开销
  • 目前最推荐的方式

6. 枚举实现(Effective Java推荐)

public enum EnumSingleton {INSTANCE;public void doSomething() {// 业务方法}
}

优点

  • 线程安全
  • 防止反射攻击
  • 防止反序列化重新创建对象
  • 代码简洁
  • Joshua Bloch在《Effective Java》中推荐的方式

如何选择

  1. 简单场景:饿汉式或枚举方式
  2. 需要懒加载:静态内部类方式
  3. 非常注重性能:双重检查锁定(但要注意正确实现)
  4. 最佳实践推荐:枚举方式或静态内部类方式

注意事项

  1. 防止反射攻击:可以在构造函数中添加检查
  2. 防止反序列化:实现readResolve()方法
  3. 在分布式/集群环境中,这些单例实现仅适用于单个JVM

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

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

相关文章

数字化零售如何全面优化顾客体验

一、引言 数字化零售是互联网、大数据、人工智能等技术在零售业中的应用,是现代零售业发展的必然趋势。随着线上购物、移动支付和全渠道销售的普及,零售行业发生了颠覆性的变化。数字化零售不仅提高了企业运营效率,更为顾客提供了便捷、个性化…

rabbitmq 交换机、队列和消息概念

RabbitMQ 是一个功能强大的消息中间件,它采用发布-订阅模式进行消息传递。下面为你详细介绍 RabbitMQ 中交换机、队列和消息的核心概念。 交换机(Exchange) 交换机在 RabbitMQ 中扮演着接收生产者发送消息的角色,它会根据特定的…

记录一次jenkins slave因为本地安装多个java版本导致的问题

今天,使用jenkins打包,发现slave掉线,上对应机器一看,好家伙,slave运行不起来了。命令行,java -vesion. 没反应,不会是哪个天杀的把java 给卸载了吧! 赶紧 where java看下。 还好 ja…

Java中Redis常用的API及其对应的原始API

相信大家写redis的时候经常忘记一些指令吧[狗头][狗头],这里整理了一下 一、 String(字符串类型) 1.代码块 // 设置字符串值 stringRedisTemplate.opsForValue().set("key", "value"); // Redis: SET key value// 设置…

C#使用ExcelDataReader高效读取excel文件写入数据库

分享一个库ExcelDataReader ,它专注读取、支持 .xls/.xlsx、内存优化。 首先安装NuGet 包 dotnet add package ExcelDataReader dotnet add package System.Text.Encoding.CodePages 编码 内存优化​​:每次仅读取一行,适合处理百万级数据…

雪豹速清APP:高效清理,畅享流畅手机体验

在智能手机的日常使用中,随着时间的推移,手机中会积累大量的垃圾文件,如临时文件、缓存数据、无用的安装包等。这些垃圾文件不仅会占用宝贵的存储空间,还会导致手机运行缓慢,甚至出现卡顿现象。为了解决这一问题&#…

关于使用v-bind绑定多个属性值的问题

背景。自定义表单开发。属性值过多,都写死很臃肿而且不方便维护。通过v-bind绑定非常方便。但是问题又来了。改以怎样的方式处理呢。返回值的格式需要注意 下面是两张动态处理v-bind属性的方法。第一张是写在了方法里面,第二张使用了虚拟属性。使用虚拟…

基于CNN的FashionMNIST数据集识别6——DenseNet模型

源码 import torch from torch import nn from torchsummary import summary""" DenseNet的核心组件:稠密层(DenseLayer) 实现特征复用机制,每个层的输出会与所有前序层的输出在通道维度拼接 """class DenseLayer(nn.Mod…

MySQL 中 INSERT ... ON DUPLICATE KEY UPDATE 为什么会导致主键自增失效?

最近开发的过程中,使用ai生成代码,写了一条这样的SQL:INSERT … ON DUPLICATE KEY UPDATE,然后发现一个奇怪的现象: 为什么使用这个语法后,自增主键(AUTO_INCREMENT)的值会跳跃甚至…

jenkins流水线打包vue无权限

jenkins在使用npm命令进行拉取依赖时,创建目录会报错无权限,如下如所示 这是因为npm 出于安全考虑不支持以 root 用户运行,即使你用 root 用户身份运行了,npm 会自动转成一个叫 nobody 的用户来运行,而这个用户权限非常低 若需要…

快速实现golang的grpc服务

文章目录 1、安装服务2、检查安装版本情况3、编写proto文件4、生成代码5、实现业务逻辑6、创建provider7、测试调用 1、安装服务 1、protoc安装 需去官网下载 protobuf 2、命令行安装protoc-gen-go和protoc-gen-go-grpc $ go install google.golang.org/protobuf/cmd/protoc-…

C++ 学习 多线程 2025年6月17日18:41:30

多线程(标准线程库 <thread>) 创建线程 #include <iostream> #include <thread>void hello() {std::cout << "Hello from thread!\n"; }int main() {// 创建线程并执行 hello() std::thread t(hello); //线程对象&#xff0c;传入可调用对…

常见的测试工具及分类

Web测试工具是保障Web应用质量的核心支撑&#xff0c;根据测试类型&#xff08;功能、性能、安全、自动化等&#xff09;和场景需求&#xff0c;可分为多个类别。以下从​​八大核心测试类型​​出发&#xff0c;梳理常见工具及其特点、适用场景&#xff1a; ​​一、功能测试工…

七牛存储sdk在springboot完美集成和应用 七牛依赖 自动化配置

文章目录 概要依赖配置属性配置类配置文件业务层控制层运行结果亮点 概要 七牛存储很便宜的&#xff0c;在使用项目的用好官方封装好的sdk&#xff0c;结合springboot去使用很方便&#xff0c;我本地用的是springoot3spring-boot-autoconfigure 依赖 <dependency><…

Java相关-链表-设计链表-力扣707

你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果是双向链表&#xff0c;则还需要属性 prev 以指示链表中的上一个节点…

C# 关于LINQ语法和类型的使用

常用语法&#xff0c;具体问题具体分析 1. Select2. SelectMany3. Where4. Take5. TakeWhile6. SkipWhile7. Join8. GroupJoin9. OrderBy10. OrderByDescending11. ThenBy12. Concat13. Zip14. Distinct15. Except16. Union17. Intersect18. Concat19. Reverse20. SequenceEqua…

华为OD-2024年E卷-小明周末爬山[200分] -- python

问题描述&#xff1a; 题目描述 周末小明准备去爬山锻炼&#xff0c;0代表平地&#xff0c;山的高度使用1到9来表示&#xff0c;小明每次爬山或下山高度只能相差k及k以内&#xff0c;每次只能上下左右一个方向上移动一格&#xff0c;小明从左上角(0,0)位置出发 输入描述 第一行…

Android:使用OkHttp

1、权限&#xff1a; <uses-permission android:name"android.permission.INTERNET" /> implementation com.squareup.okhttp3:okhttp:3.4.1 2、GET&#xff1a; new XXXTask ().execute("http://192.168.191.128:9000/xx");private class XXXTask…

Vue3+Element Plus动态表格列宽设置

在 Vue3 Element Plus 中实现动态设置表格列宽&#xff0c;可以通过以下几种方式实现&#xff1a; 方法 1&#xff1a;动态绑定 width 属性&#xff08;推荐&#xff09; vue 复制 下载 <template><el-table :data"tableData" style"width: 100%…

【JVM目前使用过的参数总结】

JVM参数总结 笔记记录 JVM-栈相关JVM-方法区(元空间)相关JVM-堆相关 JVM-栈相关 .-XX:ThreadStackSize1M -Xss1m 上面的简写形式【设置栈的大小】 JVM-方法区(元空间)相关 -XX:MaxMetaspaceSize10m 【设置最大元空间大小】 JVM-堆相关 -XX:MaxHeapSize10m -Xmx10m 上面的简写形…