Java 中的单例模式

引言:

        在 Java 编程中,单例模式是一种常见的设计模式,它保证一个类只能创建一个实例,并提供一个全局访问点。单例模式在很多场景下都非常有用,比如线程池、日志系统、数据库连接池等。本文将详细介绍 Java 中单例模式的实现方式,并通过示例说明其在实际应用中的应用场景。

一、单例模式的实现方式

在 Java 中,实现单例模式有多种方式,常见的包括:

  1. 懒汉式(Lazy Initialization):在第一次调用时才创建实例。
  2. 饿汉式(Eager Initialization):在类加载时就创建实例。
  3. 双重检查锁(Double-Checked Locking):通过双重检查加锁来确保只有一个实例被创建。
  4. 静态内部类(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 接口,在进行反序列化时可能会破坏单例模式。
  • 对象创建时机不可控:由于是在类加载时创建实例,因此无法控制实例创建的时机。

总结:

         在选择单例模式的实现方式时,需要根据具体的应用场景和需求综合考虑。如果需要延迟加载、并且在多线程环境下保证线程安全,可以选择双重检查锁单例模式或者静态内部类单例模式;如果希望在应用程序启动时就创建实例,并且不考虑性能问题,可以选择饿汉式单例模式;如果需要延迟加载并且希望代码简洁、安全可靠,可以选择静态内部类单例模式。在实际应用中,需要根据具体情况选择合适的单例模式实现方式,以确保程序的正确性和性能。

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

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

相关文章

百度资源平台链接提交

百度资源平台是百度搜索引擎提供的一个重要工具,用于帮助网站主将自己的网站链接提交给百度搜索引擎,以便更快地被收录和展示在搜索结果中。以下将就百度资源平台链接提交的概念、操作方法以及其对网站收录和曝光的影响进行探讨: 什么是百度资…

字符串(java)

字符串的特点: 1.String是java定义好的一个类,定义在java.lang包里面,所以使用的时候是不需要进行导包的 2.java程序中的所有字符串文字,都被实为此类的对象。也就是说当我们就算是进行赋值,这个也会创造…

【MATLAB源码-第173期】基于matlab的RS编码的2FSK通信系统误码率仿真,通过AWGN信道输出误码率曲线。

操作环境: MATLAB 2022a 1、算法描述 通信系统的基本框架 在现代通信系统中,数据的传输通常涉及四个基本步骤:源编码、信道编码、调制和传输。源编码主要负责压缩数据,减少传输的数据量。信道编码则通过添加冗余信息来提高传输…

【Laravel】06 数据库迁移工具migration

【Laravel】06 数据库迁移工具migration 1.migration文件目录2. 举例 1.migration文件目录 2. 举例 (base) ➜ example-app php artisan migrate Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_crea…

博客页面---前端

目录 主页 HTML CSS 文章详细页面 HTML CSS 登录页面 HTML CSS 文章编辑页 HTML CSS 这只是前端的页面组成&#xff0c;还没有接入后端&#xff0c;并不是完全体 主页 HTML <!DOCTYPE html> <!-- <html lang"en"> --> <head>&…

在 C#和ASP.NET Core中创建 gRPC 客户端和服务器

关于gRPC和Google protobuf gRPC 是一种可以跨语言运行的现代高性能远程过程调用 (RPC) 框架。gRPC 实际上已经成为 RPC 框架的行业标准&#xff0c;Google 内外的组织都在使用它来从微服务到计算的“最后一英里”&#xff08;移动、网络和物联网&#xff09;的强大用例。 gRP…

Multi-task Lung Nodule Detection in Chest Radiographs with a Dual Head Network

全局头增强真的有用吗&#xff1f; 辅助信息 作者未提供代码

如何区分相对路径 与 绝对路径?

在网页中有很多需要使用我们URL路径的场景&#xff0c;包括a标签的href、link标签的href、script标签的src、imag标签的src、form中的action、ajax请求的url等等等等。它们都可以使用相对路径和绝对路径来引入文件&#xff0c;那么&#xff0c;我们如何区分相对路径与绝对路径呢…

Unix中的进程和线程-2

1.进程对环境变量的操作 在Linux中&#xff0c;你可以使用以下几个函数来操作环境变量&#xff1a; getenv: 获取环境变量值。setenv: 设置或修改环境变量值。unsetenv: 删除环境变量 getenv: 参数&#xff1a;接受一个字符串作为参数&#xff0c;表示要获取的环境变量的名称。…

【刷题】数据结构——树状数组

一、简介 树状数组用于两种操作&#xff1a; 快速求前缀和 O ( l o g n ) O(logn) O(logn)修改某一个数 O ( l o g n ) O(logn) O(logn) 这两个操作也可以用其他方法结构完成&#xff1a; 用一个数组存每个数&#xff1a;操作1. O ( n ) O(n) O(n)&#xff0c;遍历前n个数求…

Kubernetes(k8s)架构原理

比如在服务器上部署一个博客应用服务,但是太过受欢迎,访问量太大,应用服务经常会挂,使用自动重启工具,并且将应用服务部署在了好几个服务器上,总算抗住了。后来又上线了商城应用服务和语言应用服务,随着应用服务变多,需求也千奇百怪,有的应用服务不希望被外网访问,有…

[Flutter]打包IPA

1.直接使用Xcode运行iOS工程 不用flutter构建&#xff0c;在Xcode中是可以独立进行构建运行和打包发布的。 1).运行项目 先将flutter的build清理 $ flutter clean $ flutter pub get 然后立即用XCode打开iOS工程运行 运行会报错&#xff1a; error: The sandbox is not …

壁纸小程序Vue3(首页布局)

1.创建一个公共目录common来存放css和images App.vue中引用 <style lang"scss"> /*每个页面公共css */ import common/style/common-style.scss; </style> 2.渲染轮播图 <template><view class"homeLayout"><vi…

Godot 4 教程《勇者传说》依赖注入 学习笔记(0):环境配置

文章目录 前言相关地址环境配置初始化环境配置文件夹结构代码结构代码运行 资源文件导入像素风格窗口环境设置背景设置,Tileap使用自动TileMap 人物场景动画节点添加站立节点添加移动动画添加 通过依赖注入获取Godot的全局属性项目声明 当前项目逻辑讲解角色下降添加代码位置问…

【51单片机入门记录】IIC总线协议 EEPROM存储器AT24C02概述

一、IIC总线协议概述 &#xff08;1&#xff09;IIC&#xff08;Inter-IntegratedCircuit&#xff09;总线 是一种由PHILIPS公司开发的两线式串行总线&#xff0c;用于连接微控制器以及其外围设备。IIC也被成为I2C/IC&#xff0c;其实两者是完全相同的&#xff0c;只是名词不…

Linux(CentOS7)配置系统服务以及开机自启动

目录 前言 两种方式 /etc/systemd/system/ 进入 /etc/systemd/system/ 文件夹 创建 nginx.service 文件 重新加载 systemd 配置文件 ​编辑 配置开机自启 /etc/init.d/ 进入 /etc/init.d/ 文件夹 创建 mysql 文件 编写脚本内容 添加/删除系统服务 配置开机自启 …

精通Go语言文件上传:深入探讨r.FormFile函数的应用与优化

1. 介绍 1.1 概述 在 Web 开发中&#xff0c;文件上传是一项常见的功能需求&#xff0c;用于允许用户向服务器提交文件&#xff0c;如图像、文档、视频等。Go 语言作为一门强大的服务器端编程语言&#xff0c;提供了方便且高效的方式来处理文件上传操作。其中&#xff0c;r.F…

9.动态规划——2.最大序列和

例题——最大序列和 找状态 思路一&#xff08;&#xff09; 定义一个状态 d p [ i ] dp[i] dp[i]&#xff0c;计为前i个数构成子序列和的最大值 此法状态转移比较困难&#xff0c;即若 d p [ i ] dp[i] dp[i]与 d p [ i − 1 ] dp[i-1] dp[i−1]没有明确的关系&#xff0c;有…

Ribbon有哪些负载均衡策略

负载均衡类都实现了IRule接口。 RandomRule&#xff1a;随机的选用一个实例 RoundRobinRule&#xff1a;轮询的使用实例 RetryRule&#xff1a;在轮询的基础上加了一个错误重试机制&#xff0c;在deadline时间内会不断的重试 WeightResponeTimeRule&#xff1a;根据权重去做…

【计算机网络】四层负载均衡和七层负载均衡

前言 1、分层方式 首先我们知道&#xff0c;在计算机网络中&#xff0c;常用的协议分层方式&#xff1a;OSI和TCP/IP&#xff0c;以及实际生产中使用的协议划分方式。 在OSI中&#xff0c;各层的职责如下&#xff1a; 应用层&#xff1a;对软件提供接口以使程序能使用网络服…