成人高考录取查询/seo实战密码

成人高考录取查询,seo实战密码,网站可以做软件检测吗,z blog和wordpress一、单例设计模式的基本概念 在 Java 编程的广阔天地里,单例设计模式宛如一颗璀璨的明星,是一种极为实用的创建型设计模式。它的核心使命是确保一个类在整个应用程序的生命周期内仅仅存在一个实例,并且为外界提供一个全局唯一的访问点来获取…

一、单例设计模式的基本概念

在 Java 编程的广阔天地里,单例设计模式宛如一颗璀璨的明星,是一种极为实用的创建型设计模式。它的核心使命是确保一个类在整个应用程序的生命周期内仅仅存在一个实例,并且为外界提供一个全局唯一的访问点来获取这个珍贵的实例。

想象一下,在一个大型的软件系统中,数据库连接池就像是一座城市的供水系统,需要稳定且唯一的管理;日志记录器则如同城市的档案馆,所有的信息都应该汇聚到一处。如果这些关键资源被随意创建多个实例,就好比城市有多个独立的供水系统和档案馆,不仅会造成资源的极大浪费,还可能引发数据不一致等严重问题,导致整个系统陷入混乱。而单例模式就像是一位精明的城市规划师,严格把控着实例的创建,保证一切井然有序。

二、单例设计模式的多种实现方式

1. 饿汉式单例

原理

饿汉式单例就像是一个“急性子”,在类加载的时候就迫不及待地创建了单例实例,不管后续是否会真正使用到这个实例。这种方式巧妙地利用了 Java 的类加载机制,天然地避免了多线程环境下的同步问题。

示例代码
class A {// 在类加载时就创建单例实例private static final A INSTANCE = new A();// 私有构造函数,防止外部通过 new 关键字创建实例private A() {}// 提供一个公共的静态方法,用于获取单例实例public static A getInstance() {return INSTANCE;}
}
为什么使用 static final 修饰 INSTANCE
  • static 关键字的作用:在 Java 中,static 关键字用于修饰类的成员(变量或方法),使其属于类本身,而不是类的某个实例。当一个变量被声明为 static 时,它在内存中只有一份拷贝,被所有该类的实例共享。在单例模式中,我们希望 INSTANCE 是一个全局唯一的实例,使用 static 修饰可以确保无论创建多少个 A 类的实例(实际上单例模式不允许外部创建多个实例),INSTANCE 始终只有一个。而且,由于 static 变量在类加载时就会被初始化,所以 INSTANCE 会在类加载阶段就被创建出来。

  • final 关键字的作用final 关键字用于修饰变量时,表示该变量是一个常量,一旦被赋值就不能再被修改。在单例模式中,我们希望 INSTANCE 是一个不可变的引用,即它一旦指向了某个 A 类的实例,就不能再指向其他实例。使用 final 修饰 INSTANCE 可以保证这一点,避免在程序运行过程中意外地改变 INSTANCE 的引用,从而破坏单例的唯一性。

代码验证
public class EagerSingletonTest {public static void main(String[] args) {A instance1 = A.getInstance();A instance2 = A.getInstance();// 验证两个实例是否为同一个对象System.out.println(instance1 == instance2); }
}

当你运行上述验证代码,如果输出结果为 true,就说明 instance1instance2 实际上是同一个对象,也就证明了 A 类确实是单例的。

优缺点分析
  • 优点:实现方式简单直接,而且天生具备线程安全性,无需额外的同步操作。由于类加载过程是由 JVM 保证线程安全的,所以在多线程环境下也不会出现创建多个实例的问题。
  • 缺点:如果单例实例的创建过程比较耗时,或者会占用大量的系统资源,而在整个程序的运行过程中这个实例可能根本不会被使用,那么就会造成不必要的资源浪费。

2. 懒汉式单例(非线程安全)

原理

懒汉式单例则像是一个“拖延症患者”,它不会在类加载时就创建实例,而是等到第一次真正使用这个实例的时候才去创建。这种方式实现了延迟加载,避免了不必要的资源提前消耗。

示例代码
class B {// 声明一个静态变量,用于存储单例实例,但不立即初始化private static B INSTANCE;// 私有构造函数,防止外部通过 new 关键字创建实例private B() {}// 提供一个公共的静态方法,用于获取单例实例public static B getInstance() {if (INSTANCE == null) {INSTANCE = new B();}return INSTANCE;}
}
为什么使用 static 修饰 INSTANCE

同样,使用 static 修饰 INSTANCE 是为了确保它是一个全局唯一的变量,被所有 B 类的实例(虽然单例模式下通常不会有多个实例)共享。而且,getInstance() 方法是静态方法,静态方法只能访问静态变量,所以 INSTANCE 必须是静态的才能在 getInstance() 方法中被访问。

代码验证
public class LazySingletonNonThreadSafeTest {public static void main(String[] args) {B instance1 = B.getInstance();B instance2 = B.getInstance();// 验证两个实例是否为同一个对象System.out.println(instance1 == instance2); }
}

同样,运行上述验证代码,若输出为 true,则表明 B 类在单线程环境下是单例的。

优缺点分析
  • 优点:实现了延迟加载,只有在真正需要使用实例的时候才会创建,避免了资源的提前浪费。
  • 缺点:这种实现方式在多线程环境下是不安全的。想象一下,当多个线程同时进入 if (INSTANCE == null) 这个条件判断语句时,可能会导致多个线程都认为 INSTANCEnull,从而各自创建一个实例,破坏了单例的唯一性。

3. 懒汉式单例(线程安全,使用同步方法)

原理

为了解决懒汉式单例在多线程环境下的不安全问题,我们可以在 getInstance() 方法上添加 synchronized 关键字。这样一来,在多线程环境下,同一时间就只有一个线程能够进入这个方法,从而保证了单例的唯一性。

示例代码
class C {// 声明一个静态变量,用于存储单例实例,但不立即初始化private static C INSTANCE;// 私有构造函数,防止外部通过 new 关键字创建实例private C() {}// 使用 synchronized 关键字修饰方法,保证线程安全public static synchronized C getInstance() {if (INSTANCE == null) {INSTANCE = new C();}return INSTANCE;}
}
为什么使用 static 修饰 INSTANCEgetInstance() 方法

INSTANCE 使用 static 修饰的原因和前面一样,是为了保证它是全局唯一的变量。而 getInstance() 方法使用 static 修饰是因为我们希望通过类名直接调用这个方法来获取单例实例,而不需要创建类的实例。同时,由于 getInstance() 方法要访问静态变量 INSTANCE,所以它也必须是静态方法。

代码验证
public class LazySingletonThreadSafeTest {public static void main(String[] args) {C instance1 = C.getInstance();C instance2 = C.getInstance();// 验证两个实例是否为同一个对象System.out.println(instance1 == instance2); }
}

运行验证代码,输出 true 就说明 C 类在多线程环境下也是单例的。

优缺点分析
  • 优点:保证了在多线程环境下的线程安全性,同时也实现了延迟加载。
  • 缺点:由于每次调用 getInstance() 方法都需要进行同步操作,这会带来一定的性能开销,尤其是在高并发的场景下,性能问题会更加明显。

4. 双重检查锁定单例

原理

双重检查锁定单例结合了懒汉式和同步机制的优点。它首先在不进行同步的情况下检查 INSTANCE 是否为 null,如果不为 null 则直接返回实例,这样可以减少同步的开销。只有当 INSTANCEnull 时,才会进行同步操作,并且在同步块内部再次检查 INSTANCE 是否为 null,以确保在多线程环境下不会创建多个实例。同时,为了避免指令重排序问题,需要使用 volatile 关键字修饰 INSTANCE 变量。

示例代码
class D {// 使用 volatile 关键字保证可见性,避免指令重排序private static volatile D INSTANCE;// 私有构造函数,防止外部通过 new 关键字创建实例private D() {}public static D getInstance() {if (INSTANCE == null) {synchronized (D.class) {if (INSTANCE == null) {INSTANCE = new D();}}}return INSTANCE;}
}
为什么使用 staticvolatile 修饰 INSTANCE
  • static 修饰的原因:和前面几种实现方式一样,使用 static 修饰 INSTANCE 是为了保证它是全局唯一的变量,被所有 D 类的实例共享。
  • volatile 修饰的原因:在 Java 中,指令重排序是指编译器和处理器为了提高性能,可能会对代码的执行顺序进行重新排序。在创建对象的过程中,可能会出现指令重排序的情况,导致 INSTANCE 引用在对象还未完全初始化时就被赋值。在多线程环境下,其他线程可能会看到一个未完全初始化的对象,从而引发错误。使用 volatile 关键字修饰 INSTANCE 可以禁止指令重排序,保证在多线程环境下的可见性和正确性。
代码验证
public class DoubleCheckedLockingSingletonTest {public static void main(String[] args) {D instance1 = D.getInstance();D instance2 = D.getInstance();// 验证两个实例是否为同一个对象System.out.println(instance1 == instance2); }
}

运行验证代码,若输出为 true,则证明 D 类是单例的。

优缺点分析
  • 优点:既保证了线程安全,又实现了延迟加载,同时还减少了同步带来的性能开销,是一种比较优秀的实现方式。
  • 缺点:实现相对复杂,需要开发者深入理解 volatile 关键字和双重检查的原理。

5. 静态内部类单例

原理

静态内部类单例利用了 Java 静态内部类的特性。静态内部类在类加载时不会被加载,只有在第一次使用时才会被加载,并且类加载的过程是线程安全的。因此,这种方式既实现了延迟加载,又保证了线程安全。

示例代码
class E {// 私有构造函数,防止外部通过 new 关键字创建实例private E() {}// 静态内部类,包含一个静态常量 INSTANCE,用于存储单例实例private static class SingletonHolder {private static final E INSTANCE = new E();}// 提供一个公共的静态方法,用于获取单例实例public static E getInstance() {return SingletonHolder.INSTANCE;}
}
为什么内部类的 INSTANCE 使用 static final 修饰
  • static 修饰的原因:使用 static 修饰 INSTANCE 是为了确保它是静态内部类 SingletonHolder 的静态成员,在类加载时就被初始化,并且被所有 E 类的实例共享。
  • final 修饰的原因:和前面一样,final 修饰 INSTANCE 是为了保证它是一个不可变的引用,一旦指向了某个 E 类的实例,就不能再指向其他实例,从而保证单例的唯一性。
代码验证
public class StaticInnerClassSingletonTest {public static void main(String[] args) {E instance1 = E.getInstance();E instance2 = E.getInstance();// 验证两个实例是否为同一个对象System.out.println(instance1 == instance2); }
}

运行验证代码,输出 true 就表明 E 类是单例的。

优缺点分析
  • 优点:线程安全,实现了延迟加载,代码简洁易懂,是一种比较推荐的实现方式。
  • 缺点:需要开发者对 Java 静态内部类的加载机制有一定的了解。

6. 枚举单例

原理

Java 的枚举类型天生就是线程安全的,并且可以防止反序列化重新创建新的对象。因此,使用枚举来实现单例模式是一种非常简洁、高效且安全的方式。

示例代码
enum F {INSTANCE;public void doSomething() {System.out.println("Doing something...");}
}
枚举实现单例的优势

枚举类型在 Java 中是一种特殊的类,它的实例是有限且唯一的。在枚举类型中定义的枚举常量(如 INSTANCE)会在类加载时被创建,并且是线程安全的。同时,Java 的序列化机制对枚举类型有特殊的处理,反序列化时不会创建新的实例,从而保证了单例的唯一性。

代码验证
public class EnumSingletonTest {public static void main(String[] args) {F instance1 = F.INSTANCE;F instance2 = F.INSTANCE;// 验证两个实例是否为同一个对象System.out.println(instance1 == instance2); }
}

运行验证代码,若输出为 true,则说明 F 枚举类型实现了单例。

优缺点分析
  • 优点:线程安全,防止反序列化重新创建新的对象,实现简单,是实现单例模式的最佳方式之一。
  • 缺点:相对不够灵活,因为枚举类型默认继承 java.lang.Enum 类,所以不能再继承其他类。

三、单例设计模式的使用场景

  • 资源共享:在一些需要多个模块共享同一个资源的场景中,如数据库连接池、线程池等,使用单例模式可以确保资源的一致性和高效利用。因为多个实例可能会导致资源的冲突和浪费,而单例模式可以保证只有一个实例来管理这些资源。
  • 配置管理:应用程序的配置信息通常只需要一个实例来管理。使用单例模式可以方便地获取和修改配置信息,避免了多个实例对配置信息的不一致修改。
  • 日志记录:日志记录器通常是单例的,这样可以确保所有的日志信息都被记录到同一个地方,方便后续的查看和分析。如果有多个日志记录器实例,可能会导致日志信息分散,不利于管理。

四、单例设计模式的注意事项

序列化和反序列化问题

如果单例类实现了 Serializable 接口,在反序列化时可能会创建新的实例,从而破坏单例的唯一性。为了解决这个问题,需要重写 readResolve() 方法。

import java.io.ObjectStreamException;
import java.io.Serializable;class G implements Serializable {private static final G INSTANCE = new G();private G() {}public static G getInstance() {return INSTANCE;}// 重写 readResolve() 方法,防止反序列化创建新的实例private Object readResolve() throws ObjectStreamException {return INSTANCE;}
}

反射攻击问题

通过反射机制可以调用私有构造函数创建新的实例,这也会破坏单例的唯一性。为了防止反射攻击,可以在构造函数中添加判断逻辑。

class H {private static final H INSTANCE = new H();private static boolean isInstanceCreated = false;private H() {if (isInstanceCreated) {throw new IllegalStateException("Singleton instance already created!");}isInstanceCreated = true;}public static H getInstance() {return INSTANCE;}
}

五、总结

单例设计模式在 Java 开发中是一种非常实用的设计模式,它可以确保一个类只有一个实例,避免了资源的浪费和数据不一致的问题。在使用单例模式时,还需要注意序列化和反序列化、反射攻击等问题,确保单例的唯一性和安全性。

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

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

相关文章

DeepSeek 助力 Vue3 开发:打造丝滑的弹性布局(Flexbox)

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…

DeepSeek开源周Day5压轴登场:3FS与Smallpond,能否终结AI数据瓶颈之争?

2025年2月28日,DeepSeek开源周迎来了第五天,也是本次活动的收官之日。自2月24日启动以来,DeepSeek团队以每天一个开源项目的节奏,陆续向全球开发者展示了他们在人工智能基础设施领域的最新成果。今天,他们发布了Fire-F…

SQL AnyWhere 的备份与恢复

目录 一、备份 二、恢复 1、自动恢复 2、映像恢复 3、日志恢复-指定时间点 4、日志恢复-指定偏移 5、完整的恢复流程 6、恢复最佳实践 三、其他操作 1、dbtran 2、SQL Shell 工具 数据库的安装与基本使用内容请参考博客: SAP SQLAnyWhere 17 的安装与基本使用_sql…

入门基础项目(SpringBoot+Vue)

文章目录 1. css布局相关2. JS3. Vue 脚手架搭建4. ElementUI4.1 引入ElementUI4.2 首页4.2.1 整体框架4.2.2 Aside-logo4.2.3 Aside-菜单4.2.4 Header-左侧4.2.5 Header-右侧4.2.6 iconfont 自定义图标4.2.7 完整代码 4.3 封装前后端交互工具 axios4.3.1 安装 axios4.3.2 /src…

unity学习61:UI布局layout

目录 1 布局 layout 1.1 先准备测试UI,新增这样一组 panel 和 image 1.2 新增 vertical layout 1.3 现在移动任意一个image 都会影响其他 1.3.1 对比 如果没有这个,就会是覆盖效果了 1.3.2 对比 如果没有这个,就会是覆盖效果了 1.4 总结&#xf…

翻译: 深入分析LLMs like ChatGPT 一

大家好,我想做这个视频已经有一段时间了。这是一个全面但面向普通观众的介绍,介绍像ChatGPT这样的大型语言模型。我希望通过这个视频让大家对这种工具的工作原理有一些概念性的理解。 首先,我们来谈谈你在这个文本框里输入内容并点击回车后背…

Python 实战:构建分布式文件存储系统全解析

Python 实战:构建分布式文件存储系统全解析 在当今数据爆炸的时代,分布式文件存储系统凭借其高可扩展性、高可靠性等优势,成为了数据存储领域的热门选择。本文将详细介绍如何使用 Python 构建一个简单的分布式文件存储系统。从系统架构设计&…

tableau之标靶图、甘特图和瀑布图

一、标靶图 概念 标靶图(Bullet Chart)是一种用于显示数据与目标之间关系的可视化图表,常用于业务和管理报告中。其设计旨在用来比较实际值与目标值,同时展示额外的上下文信息(如趋势)。 作用 可视化目标…

Linux下的网络通信编程

在不同主机之间,进行进程间的通信。 1解决主机之间硬件的互通 2.解决主机之间软件的互通. 3.IP地址:来区分不同的主机(软件地址) 4.MAC地址:硬件地址 5.端口号:区分同一主机上的不同应用进程 网络协议…

530 Login fail. A secure connection is requiered(such as ssl)-java发送QQ邮箱(简单配置)

由于cs的csdN许多文章关于这方面的都是vip文章,而本文是免费的,希望广大网友觉得有帮助的可以多点赞和关注! QQ邮箱授权码到这里去开启 授权码是16位的字母,填入下面的mail.setting里面的pass里面 # 邮件服务器的SMTP地址 host…

SOME/IP-SD -- 协议英文原文讲解6

前言 SOME/IP协议越来越多的用于汽车电子行业中,关于协议详细完全的中文资料却没有,所以我将结合工作经验并对照英文原版协议做一系列的文章。基本分三大块: 1. SOME/IP协议讲解 2. SOME/IP-SD协议讲解 3. python/C举例调试讲解 5.1.3.1 E…

【Linux】learning notes(3)make、copy、move、remove

文章目录 1、mkdir (make directory)2、rmdir (remove directory)3、rm(remove)4、>5、touch 新建文件6、mv(move)7、cp(copy) 1、mkdir (make…

智能AI替代专家系统(ES)、决策支持系统(DSS)?

文章目录 前言一、专家系统(ES)是什么?二、决策支持系统(DSS)是什么?1.决策支持系统定义2.决策系统的功能与特点3.决策支持系统的组成 三、专家系统(ES)与决策支持系统(D…

实现Python+Django+Transformers库中的BertTokenizer和BertModel来进行BERT预训练,并将其应用于商品推荐功能

一、环境安装准备 #git拉取 bert-base-chinese 文件#创建 虚拟运行环境python -m venv myicrplatenv#刷新source myicrplatenv/bin/activate#python Django 集成nacospip install nacos-sdk-python#安装 Djangopip3 install Django5.1#安装 pymysql settings.py 里面需要 # 强制…

Qt Creator + CMake 构建教程

此教程基于: Qt 6.7.4Qt Creator 15.0.1CMake 3.26.4 Qt 6 以下的版本使用 CMake 构建可能会存在一些问题. 目录 新建窗体工程更新翻译添加资源软件部署(Deploy) 此教程描述了如何一步步在 Qt Creator 中使用 CMake 构建应用程序工程. 涉及 新建窗体工程, 更新翻译, 添加资源, …

5个GitHub热点开源项目!!

1.自托管 Moonlight 游戏串流服务:Sunshine 主语言:C,Star:14.4k,周增长:500 这是一个自托管的 Moonlight 游戏串流服务器端项目,支持所有 Moonlight 客户端。用户可以在自己电脑上搭建一个游戏…

【Mark】记录用宝塔+Nginx+worldpress+域名遇到的跨域,301,127.0.0.1,CSS加载失败问题

背景 想要用宝塔搭建worldpress,然后用域名直接转https,隐藏掉ipport。 结果被折磨了1天,一直在死活在301,127.0.0.1打转 还有css加载不了的情况 因为worldpress很多是301重定向的,所以改到最后我都不知道改了什么&am…

基于Kerberos认证对接华为云Elasticsearch

可以通过华为官方提供的Elasticsearch Java客户端(基于Elasticsearch官方版本改造),实现基于Kerberos认证访问和操作华为云Elasticsearch;亦可以使用更加通用的开源Elasticsearch Java客户端bboss,实现基于Kerberos认证…

【湖北省计算机信息系统集成协会主办,多高校支持 | ACM出版,EI检索,往届已见刊检索】第二届边缘计算与并行、分布式计算国际学术会议(ECPDC 2025)

第二届边缘计算与并行、分布式计算国际学术会议(ECPDC 2025)将于2025年4月11日至13日在中国武汉盛大召开。本次会议旨在为边缘计算、并行计算及分布式计算领域的研究人员、学者和行业专家提供一个高水平的学术交流平台。 随着物联网、云计算和大数据技术…

CSS—背景属性与盒子模型(border、padding、margin)

目录 一.背景属性 二.盒子模型 1.边框border a. 圆角属性border-radius b. 图像属性border-image 2. 内边距padding 3. 外边距margin 3. 宽度width与高度height 一.背景属性 浏览器背景图默认是平铺效果(复制图片直至填满设置的区域大小) 背景…