Java单例模式的几种实现方式

SAP ERP销售应收&成本科目确定 ERP作为业财一体软件,其中最核心的就是业务与财务模块的自动集成,无需财务进行手工做账,提高工作效率的同时降低人工操作产生的误差。今天浅浅的分享一下SD模块生成会计凭证时,借贷项确定的系统配置。一般项目上借贷项、科目都有FICO提供,但是具体的集成配置是在SD这边。 阅读详情


一、"饿汉模式"

public class 饿汉模式 {
	public static void main(String[] args) {

		mySingleton theObject=mySingleton.getInstance();
		mySingleton theObject2=mySingleton.getInstance();
		System.out.println(theObject.hashCode()==theObject2.hashCode());//true
	}
		
}

class mySingleton {
	private static mySingleton theObject=new mySingleton();
	private mySingleton(){}
	public static mySingleton getInstance(){
	return theObject;
	}
}

使用static  在类加载时就完成对象实例的创建,之后返回同一对象  ,简单方便,但由于是立即加载的方式,难免会有些不必要的开销,比如此刻并不需要用到它

二、静态代码块("饿汉")

public class 静态代码块饿汉 {
	public static void main(String[] args) {

	mySingleton4 theObject=mySingleton4.getInstance();
	mySingleton4 theObject2=mySingleton4.getInstance();
	System.out.println(theObject.hashCode()==theObject2.hashCode());//true
	}
}


class mySingleton4 {
	private static mySingleton4 theObject=null;
	private mySingleton4(){}
	static{
		theObject=new mySingleton4();
	}
	public static mySingleton4 getInstance(){
	return theObject;
	}
}

由于静态代码块static也只进行一次,且在对象创建前执行,所以返回的也都是同一单例

三、"懒汉模式"

public class 懒汉模式 {
	public static void main(String[] args) {
		mySingleton2 theObject=mySingleton2.getInstance();
		mySingleton2 theObject2=mySingleton2.getInstance();
		System.out.println(theObject.hashCode()==theObject2.hashCode());
	}
}

class mySingleton2 {
	private static volatile mySingleton2 theObject=null;
	private mySingleton2(){}
	public static mySingleton2 getInstance(){
		if(theObject==null){
			synchronized (mySingleton2.class) {
				if(theObject==null)
					theObject=new mySingleton2();
			}
			
		}
		return theObject;
	}
}

延迟加载,在第一次用到此实例时,创建唯一对象,由于可能存在多线程安全问题,故采用DCL 双重检测锁机制,确保只创建返回一个实例(但锁同步需要开销,注意!DCL 可能会发送happen-before指令重排错误,需要对实例附加volatile !不推荐使用DCL)

四、静态内部类单例

public class 静态内部类单例 {
	public static void main(String[] args) {
		mySingleton3 myObject=mySingleton3.getInstance();
		mySingleton3 myObject2=mySingleton3.getInstance();
		System.out.println(myObject.hashCode()==myObject2.hashCode());
	}
}

class mySingleton3 {
	
	private static class SingletonHandler{
		private static mySingleton3 theObject=new mySingleton3();
	}
	private mySingleton3(){}
	
	public static mySingleton3 getInstance(){
		return SingletonHandler.theObject;
	}
}

使用静态的内部类进行延迟加载,在第一次用到本实例时,加载返回内部类的static 对象,解决了饿汉模式的不必要开销问题和懒汉模式的线程同步开销问题

五、序列化单例

public class 单例与序列化 {

	public static void main(String[] args) throws Exception{
		
			mySingleton5 myObject = mySingleton5.getInstance();
			FileOutputStream fosRef = new FileOutputStream(new File(
					"E://myObjectFile.txt"));
			ObjectOutputStream oosRef = new ObjectOutputStream(fosRef);
			oosRef.writeObject(myObject);
			oosRef.close();
			fosRef.close();
			System.out.println(myObject.hashCode());

	 		FileInputStream fisRef = new FileInputStream(new File(
					"E://myObjectFile.txt"));
			ObjectInputStream iosRef = new ObjectInputStream(fisRef);
			mySingleton5 myObject2 = (mySingleton5) iosRef.readObject();
			iosRef.close();
			fisRef.close();
			System.out.println(myObject2.hashCode());
	
	}
}


class mySingleton5 implements Serializable{
	
	private static class SingletonHandler{
		private static mySingleton5 theObject=new mySingleton5();
	}
	private mySingleton5(){}
	
	public static mySingleton5 getInstance(){
		return SingletonHandler.theObject;
	}
	protected Object readResolve() throws ObjectStreamException {
		System.out.println("调用了readResolve方法!");
		return SingletonHandler.theObject;
	}
}

由于反射机制和序列化,会在返回时调用构造器生成一个新的对象,故违反了单例的原则。且序列化时是不会与静态方法有关联的,就导致了存入文件和读取文件的对象,不是同一实例对象。解决方式是 在单例中实现 readResolve方法,返回静态的对象。

在ObjectInputStream 类的源码中,存在一个 readOrdinaryObject(boolean unshared) 方法,其中判断了序列化对象是否有readResolve() 方法,若有则会去进行调用,则可在此方法内返回我们所需要的单例对象。

private Object readOrdinaryObject(boolean unshared)
        throws IOException
    {
        //此处省略部分代码

        Object obj;
        try {
            obj = desc.isInstantiable() ? desc.newInstance() : null;
        } catch (Exception ex) {
            throw (IOException) new InvalidClassException(
                desc.forClass().getName(),
                "unable to create instance").initCause(ex);
        }

        //此处省略部分代码

        if (obj != null &&
            handles.lookupException(passHandle) == null &&
            desc.hasReadResolveMethod())
        {
            Object rep = desc.invokeReadResolve(obj);
            if (unshared && rep.getClass().isArray()) {
                rep = cloneArray(rep);
            }
            if (rep != obj) {
                handles.setObject(passHandle, obj = rep);
            }
        }

        return obj;
    }

关键在于 if 判断中desc.hasReadResolveMethod()  ,Object rep = desc.invokeReadResolve(obj);  去执行readResolve 返回创新obj 。

 关于单例与序列化可参考此引用博客:单例与序列化的那些事儿    深入分析Java的序列化与反序列化

六、枚举单例

public class enum枚举单例 {

	public static void main(String[] args) throws Exception{
		
			EnumSingleton hah=EnumSingleton.getInstance();
			EnumSingleton hah2=EnumSingleton.getInstance();
			
			mySingleton6 o1=hah.getSingleton6();
			mySingleton6 o2=hah2.getSingleton6();
			System.out.println(o1.hashCode()==o2.hashCode());
			
			EnumSingleton myObject = EnumSingleton.getInstance();
			FileOutputStream fosRef = new FileOutputStream(new File(
					"E://myObjectFile.txt"));
			ObjectOutputStream oosRef = new ObjectOutputStream(fosRef);
			oosRef.writeObject(myObject);
			oosRef.close();
			fosRef.close();
			System.out.println(myObject.getSingleton6().hashCode());
		 
			FileInputStream fisRef = new FileInputStream(new File(
					"E://myObjectFile.txt"));
			ObjectInputStream iosRef = new ObjectInputStream(fisRef);
			EnumSingleton myObject2 = (EnumSingleton) iosRef.readObject();
			iosRef.close();
			fisRef.close();
			System.out.println(myObject2.getSingleton6().hashCode());
		 
		
	}

}

enum EnumSingleton{
	SingletonHandler;
	class mySingleton6{
		private mySingleton6(){}
	}
	private mySingleton6 theObject=null;
	private EnumSingleton(){
		theObject=new mySingleton6();
	}
	public static EnumSingleton getInstance(){
		return SingletonHandler;
	}
	public mySingleton6 getSingleton6(){
		return theObject;
	} 
	
 }

采用枚举可能是最合适的一种实现单例的方式,即可以避免线程安全问题,又可以完成序列化与反序列化的事。无需自己手动添加readResolve()方法去返回。

一般使用静态内部类的方式(若需要序列化则再加上readResolve()方法)和枚举的方式,当然最好的选择是枚举方式。



MacBook 长期挂机 OpenClaw:电池保护 + 防休眠设置 本文介绍了MacBook长期挂机运行OpenClaw时的电池保护和防休眠设置方案。主要内容包括:1)电池保护策略,通过电源连接、充电限制和定期充放电维护电池健康;2)防休眠设置,禁用系统休眠、自动休眠和屏幕休眠;3)OpenClaw的Docker部署方法。文章提供了详细的命令行脚本和配置说明,帮助用户实现MacBook的长期稳定运行,同时保护电池寿命。 阅读详情

相关推荐

英飞凌TLF35584 SBC实战:手把手教你配置WDG看门狗与ERR监控(基于AUTOSAR架构)

本文详细介绍了基于AUTOSAR架构的英飞凌TLF35584 SBC芯片WDG看门狗与ERR监控功能的配置方法。通过硬件平台搭建、寄存器级配置、AUTOSAR模块集成及诊断策略优化,帮助开发者快速掌握关键配置技巧,提升嵌入式系统的安全性和可靠性。

weixin_30256901的博客 477

Java设计模式--单例模式(三种实现方式)

单例模式是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式。简单来说保证在内存中有给定数量的对象,例如内存中产生唯一一个对象,不管创建多少次,也只有唯一的对象。

YoungJIA977的博客 1641

PINN——加入物理约束的神经网络

【摘要】 基于物理信息的神经网络(Physics-informed Neural Network, 简称PINN),是一类用于解决有监督学习任务的神经网络,它不仅能够像传统神经网络一样学习到训练数据样本的分布规律,而且能够学习到数学方程描述的物理定律。与纯数据驱动的神经网络学习相比,PINN在训练过程中施加了物理信息约束,因而能用更少的数据样本学习到更具泛化能力的模型。本文主要解析这种神经网络以...

qq_39444290的博客 4584

Java 史上最全单例模式实现大全

通过本文的详细介绍,相信大家已经对单例模式有了全面的了解。从最基本的懒汉式和饿汉式,到线程安全的双重检查锁和静态内部类,再到防止序列化破坏的枚举单例,应有尽有。此外,我们还介绍了登记式/容器式单例模式和多例模式,为你提供了更多的实现选择。单例模式无疑是 Java 开发中不可或缺的利器。合理应用单例模式,不仅可以解决资源管理和状态控制的问题,还能提升程序的性能和可靠性。相信通过本文的学习,你一定能成为单例模式的行家里手,在未来的 Java 开发中大展拳脚。

赵KK的博客 2317

立创开源Link Hub多功能USB扩展坞:CH339F主控+4层板设计,实测网口/存储性能

本文深度评测了立创开源Link Hub多功能USB扩展坞,其采用CH339F主控芯片与4层PCB板设计,并严格进行阻抗匹配。实测表明,该扩展坞的USB接口与microSD读卡器性能均接近USB 2.0理论极限,百兆以太网口转换效率高,性能损失极小。设计上注重电源保护与信号完整性,是一个兼顾稳定性与成本的高完成度开源硬件项目。

weixin_36173034的博客 159

高杂合度基因组组装实战:Hifiasm参数调优与purge_dups过滤效果对比(附猪毛菜案例)

本文深入探讨了高杂合度基因组组装中Hifiasm参数调优与purge_dups过滤的实战效果对比,通过猪毛菜案例详细解析了两种方法的适用场景与优化策略。文章重点分析了purge_dups在contig过滤中的显著效果,为基因组组装提供了关键的技术参考。

weixin_29232121的博客 495

懒汉式单例模式--解决线程安全最完整版详解

懒汉式单例模式 首先我们先来回顾一下饿汉式单例模式: class Singleton{ private static Singleton singleton=new Singleton(); private Singleton(){} public static Singleton getInstrance(){ return singleton; ...

weixin_42617262的博客 2万+

Qt实现离线缓存地图(附完整源码)

Qt实现离线缓存地图(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 858

Java单例模式的实现方式解析

本文详细介绍了Java单例模式的多种实现方式,包括饿汉式、懒汉式、双重检查锁、静态内部类和枚举类等,并对各种实现方式的原理、优缺点和适用场景进行了深入分析。在实际开发中,应根据具体需求选择合适的单例实现方式。一般情况下,静态内部类和枚举类是最推荐的实现方式,它们既简单又安全,能满足大多数应用场景的需求。单例模式作为一种常用的设计模式,不仅能有效节约系统资源,还能确保数据的一致性。

weixin_56018532的博客 883

Python爬虫应对Cloudflare防护:5秒盾+Turnstile验证码实战(AST反混淆+指纹模拟,成功率95%)

Cloudflare 5秒盾+Turnstile验证码的防护核心,是通过“前端JS挑战+多维度指纹校验”确认请求来源的真实性。用AST反混淆还原CF的验证逻辑,避免执行无用代码导致的验证失败;基于真实浏览器采集指纹,确保指纹维度100%匹配真人环境;结合轻量级JS引擎和自动化工具,模拟完整的浏览器执行环境。该方案的绕过成功率可达95%(剩余5%主要是IP或请求频率导致的风控),适用于绝大多数部署CF防护的网站。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1718

基础入门篇 | YOLOv8 项目【训练】【验证】【推理】最简单教程 | YOLOv8必看 | 最新更新,直接打印 FPS,mAP50,75,95

三个文件搞定YOLOv8【训练】【验证】【推理】🚀🚀🚀

Coding... 2万+

Java单例模式有几种实现方式

利用JVM类加载机制保证线程安全。关键字确保可见性,减少同步开销。天然支持线程安全与序列化防护。

DKPT的博客 933

Android15音频进阶之解underrun与overrun思路(一百一十七)

本篇目的:Android15音频进阶之解underrun与overrun思路Underrun:发生在播放:APP准备的数据太少,导致底层没有音频数据可以播放,导致ADSP被“饿死了“,即Underrun。Overrun: 发声在录音:APP录音数据获取太慢了,导致底层录出来的数据太多了,APP播放不了,导致APP被“撑死了”,即Overrun。

Android系统攻城狮 2106

java单例模式几种实现方式

定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。 单例模式结构图: 单例模式有多种写法各有利弊,现在我们来看看各种模式写法。 1. 饿汉模式 public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){ } public static Singleton getInstance() { ...

weixin_43865381的博客 252

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Java单例模式几种实现方式

在平时的工作、学员的学习以及面试过程中,单例模式作为一种常用的设计模式,会经常被面试官问到,甚至笔试会要求学员现场默写,下面将会就单例模式的实现思路和几种常见的实现方式进行简单的分享。 单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。是最常用到的设计模...

alposbo7523的博客 179

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

java单例模式 几种_Java单例模式的几种常见实现方式

Java单例模式的几种常见实现方式懒汉or饿汉?懒汉:单例模式延迟加载方式,一开始不给你new对象,你要new再给你new饿汉:上来就给你new好一个对象,你可以直接用(吃),你也没法new饿汉:不加锁,线程安全,用起来方便,容易产生垃圾对象public class SingletonTest1 {public static void main(String[] args) {//由于构造方法是私...

weixin_31837543的博客 138

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Java实现单例模式的几种方式

1. 饿汉式 /** * 饿汉式(在类初始化时,已经自行实例化) * * @author: Charle~ * @date: 2020-03-13. **/ public class Singleton { //私有的默认构造器 private Singleton() {} private static Singleton instance = new Si...

u010986887的博客 194

Java 实现单例模式的几种方式

在Java中,单例模式有多种实现方式,每种方式都有其优点和缺点。饿汉式单例模式简单易用,但可能会浪费系统资源;懒汉式单例模式可以节约系统资源,但可能会出现线程安全问题;双重检查锁定单例模式既可以在需要时才创建对象,又可以确保线程安全,但在某些JVM中可能会出现问题;静态内部类单例模式既可以在需要时才创建对象,又可以确保线程安全,而且代码简洁优雅。根据具体的需求,选择合适的实现方式非常重要。

stormjun的博客 570

JAVA中单例模式的几种实现方式

1、饿汉式(线程安全,调用效率高,但是不能延时加载): publicclassImageLoader{ privatestaticImageLoaderinstance=newImageLoader; privateImageLoader(){} publicstaticImageLoadergetInstance(){ returninstance; } } 一上来就把单例对象创建出来了,要用的时候直接...

LHH201016的博客 175

java单例模式几种常见实现方式

什么是单例模式 因进程需要,有时我们只需要某个类同时保留一个对象,不希望有更多对象,此时,我们则应考虑单例模式的设计。 单例模式的特点 1、单例模式只能有一个实例。 2、单例类必须创建自己的唯一实例 3、单例类必须向其他对象提供这一实例。 单例模式的实现 懒汉式(线程不安全) public class SingletonDemo { private static SingletonDemo instance; private SingletonDemo(){ } ..

a904364908的博客 541

java设计模式之单例模式的几种实现方式

单例模式 单例模式确保某一个类只有一个实例,而且自行实例化,这个类提供了访问其唯一对象的方式,可以直接访问,不需要实例化该对象。 单例模式的几种实现方式 1、懒汉式(线程不安全) public class Singleton{ private static Singleton instance; //私有构造函数 private Singleton(){} ...

XTAOTWO的博客 341

java单例实现方式_Java单例模式实现的几种方式

java单例模式实现的几种方式单例模式好多书上都是这么写的:public class SingleTon1 {private SingleTon1(){}private static SingleTon1 instance = null;public static SingleTon1 getInstance(){if(instance == null){instance = new Single...

weixin_33066321的博客 114

java 单例模式实现的几种方式

饱汉模式 import java.util.Objects; /** * 线程安全的单例模式(饱汉) * * @author Chris * @date 2020/02/28 23:37 * @since 1.0.0 */ public class Singleton1 { private static volatile Singleton1 ourInstance; ...

who7708的专栏 165
上一篇: 石子合并 动态规划(直线型)
下一篇: Ubuntu下安装Redis
JumpFly_W
博客等级 码龄17年 72粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值