Java设计模式---单例模式
一、饿汉模式
/**
* @ClassName: Singleton_Simple
* @Description: 单例模式——饿汉模式
* @author Ran
* @date 2011-2-4 上午12:46:15
*
*/
public class Singleton_Simple {
private static final Singleton_Simple simple = new Singleton_Simple();
private Singleton_Simple(){}
public static Singleton_Simple getInstance(){
return simple;
}
}
说明:顾名思义,饿汉模式就是在jvm进程启动并在我们主动使用该类的时候就会在内存中初始化一个单例对象,当我们调用getInstance()的时候直接获取该对象,他的创建是在我们调用getInstance()静态方法之前!
二、懒汉模式
/**
* @ClassName: Singleton_lazy
* @Description: 单例模式——懒汉模式
* @author Ran
* @date 2011-2-4 上午12:48:41
*
*/
public class Singleton_lazy {
private static Singleton_lazy lazy = null;
private Singleton_lazy(){}
public static synchronized Singleton_lazy getInstance(){
if( lazy == null ){
lazy = new Singleton_lazy();
}
return lazy;
}
}
说明:懒汉模式是相对于饿汉模式而言的,在jvm进程启动并在我们主动使用该类的时候不会在内存中初始化一个单例对象,只有当我们调用getInstance()的时候才去创建该对象,他的创建是在我们调用getInstance()静态方法之后,为了并没现象同步问题,我们在getInstance()方法上加了一个锁,这个方法每次只允许一个线程进来,虽然同步问题是解决了,但是相应的性能问题就出现了。
三、双锁机制
/**
* @ClassName: Singleton_DoubleKey
* @Description: 单例模式——双锁机制
* @author Ran
* @date 2011-2-4 上午12:53:50
*
*/
public class Singleton_DoubleKey {
private static Singleton_DoubleKey doubleKey = null;
private Singleton_DoubleKey (){}
public static Singleton_DoubleKey getInstance(){
if( doubleKey == null ){ //①
synchronized(Singleton_DoubleKey.class){ //②
if( doubleKey == null ){ //③
doubleKey = new Singleton_DoubleKey(); //④
}
}
}
return doubleKey;
}
}
说明:双锁机制的出现是为了解决前面同步问题和性能问题,看上面的代码,简单分析下确实是解决了多线程并行进来不会出现重复new对象,而且也实现了懒加载,但是当我们静下来并结合java虚拟机的类加载过程我们就会发现问题出来了,对于JVM加载类过程不熟悉的,这里我简单介绍下,熟悉的跳过这段(当然,既然你熟悉就自然会知道双锁的弊端了)。
jvm加载一个类大体分为三个步骤:
- 加载阶段:就是在硬盘上寻找java文件对应的class文件,并将class文件中的二进制数据加载到内存中,将其放在运行期数据区的方法区中去,然后在堆区创建一个java.lang.Class对象,用来封装在方法区内的数据结构;
- 连接阶段:这个阶段分为三个步骤,步骤一:验证,验证什么呢?当然是验证这个class文件里面的二进制数据是否符合java规范咯;步骤二:准备,为该类的静态变量分配内存空间,并将变量赋一个默认值,比如int的默认值为0;步骤三:解析,这个阶段就不好解释了,将符号引用转化为直接引用,涉及到指针,这里不做多的解释;
- 初始化阶段:当我们主动调用该类的时候,将该类的变量赋于正确的值(这里不要和第二阶段的准备混淆了),举个例子说明下两个区别,比如一个类里有private static int i = 5; 这个静态变量在"准备"阶段会被分配一个内存空间并且被赋予一个默认值0,当道到初始化阶段的时候会将这个变量赋予正确的值即5,了解了吧!
好了,上面大体介绍了jvm类加载过程,回到我们的双锁机制上来分析下问题出在了哪里?假如有两个并发线程a、b,a线程主动调用了静态方法getInstance(),这时开始加载和初始化该类的静态变量,b线程调用getInstance()并等待获得同步锁,当a线程初始化对象过程中,到了第二阶段即连接阶段的准备步骤时,静态变量doubleKey 被赋予了一个默认值,但是这时还没有进行初始化,这时当a线程释放锁后,b线程判断doubleKey != null,则直接返回了一个没有初始化的doubleKey 对象,问题就出现在这里了,b线程拿到的是一个被赋予了默认值但是未初始化的对象,刚刚可以通过锁的检索!
所以对于上面的几个模式还是推荐使用第一种,在jvm加载类的时候就初始化一个对象,也避免了同步问题。
分享到:
相关推荐
这个压缩包文件“行业文档-设计装置-双锁带钢筋卡扣.zip”包含了相关的设计文档,即“双锁带钢筋卡扣.pdf”,它详细阐述了这种特殊装置的技术细节和应用。 首先,我们要理解“双锁带钢筋卡扣”的概念。这是一种用于...
单例模式(Singleton Pattern)是一种常用的软件设计模式,属于创建型模式之一。其目的是确保某个类只有一个实例,并提供一个全局访问点。单例模式的核心在于确保在系统运行期间一个类只能有一个实例存在。 #### 二...
单例模式是软件设计模式中的一种,它保证一个类只有一个实例,并提供全局访问点。这种模式在许多场景下非常有用,比如配置管理、线程池、数据库连接等,因为这些情况通常只需要一个对象来处理所有的请求,以节省系统...
标题“电子政务-双锁紧的电缆防水接头.zip”和描述中的关键词“双锁紧”和“电缆防水接头”提示我们,这个压缩包文件可能包含了关于一种特殊的电缆连接技术,它具有双重安全锁定机制和卓越的防水性能,以适应电子...
在 Java 中,单例是一种常用的设计模式,它可以确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式可以应用于各种场景,如数据库连接池、日志记录器、线程池等。但是,单例模式也存在一些缺点,如...
这种锁车器的设计着重于安全性和操作便捷性,采用双锁双控机制,提升了公共自行车系统的可靠性。 在公共交通系统中,公共自行车服务已经成为城市绿色出行的重要组成部分。为了确保车辆的安全以及方便用户的使用,锁...
这种机构可能包含了先进的升降技术和双锁止安全机制,旨在确保在变电所设备安装过程中的安全性和效率。 在变电所的建设中,机电设备的安装是关键环节,涉及到电力系统的稳定运行。机电设备包括变压器、开关设备、...
而两个基准的设计可能指的是双参考频率或者双锁相环路,这种设计可以提高系统的稳定性和精度。 描述中的“行业文档-设计装置”暗示这是一个专业领域的技术文档,可能包含了详细的接收机设计原理、步骤以及实际应用...
2. **双锁止机制**:为了保障安全,设备可能采用双重锁定系统,分别在垂直升降和水平旋转时进行锁定,防止意外移动导致的事故。 3. **斗篮设计**:斗篮是承载工作人员和工具的工作平台,其设计必须符合人体工程学,...
基于虚拟仪器技术的双锁相放大器设计在这些方面做了创新性的改进。虚拟仪器技术是一种利用计算机的强大处理能力来扩展和增强传统仪器功能的技术,使得原本需要硬件支持的功能可以通过软件来实现。 本文中介绍的双锁...
电子政务-可电子遥控的双锁舌防盗锁.zip
首先,从机械工程的角度看,双锁紧机制可能涉及到紧固件的选择、结构设计、受力分析等,以保证锁紧力度的均匀分布和足够的锁定强度。这通常需要对材料力学、连接技术有深入的理解。 其次,电气工程方面,由于是在...
- 生产者消费者模式、读者写者模式、双锁算法等,是解决并发问题的经典设计模式。 通过学习这个“concurrency-in-java”项目,你可以逐步掌握如何在Java环境中编写高效、安全的并发代码,为实际开发打下坚实基础。...
3. **双锁止机制**:这一特性是为了增加安全系数,当斗篮升至工作位置时,双重锁止系统会自动激活,确保设备在大风或其他恶劣天气条件下不会发生意外移动。双锁止设计遵循了严格的安全标准,是防止事故的重要措施。 ...
双锁紧检测装置的设计则是为了确保这些壳体的可靠封闭,防止因锁紧失效导致的设备损坏或安全事故。 这种双锁紧检测装置可能采用了先进的传感器技术和智能监控系统,能够实时监测壳体的锁紧状态。它可能包括两个独立...
"支腿可调节"的设计正是为此而生,它提供了一种方便快捷的调节机制,使得安装平台能够根据不同的地面条件进行相应的支撑腿长度调整,以确保整个平台的稳定性。在复杂的地形或地面不平整的施工环境中,该机制能有效...
2. **反应式流** (Reactive Streams):Java 9通过`java.util.concurrent.Flow`接口支持反应式编程模式,这是一种处理大量数据流的方式,特别适合并发和非阻塞I/O操作。它允许系统在高并发场景下高效地处理事件和数据...
研究优秀运动员的训练模式,如李双锁和汪红祥,有助于我们了解如何制定有效的训练计划,优化训练内容,以提高马拉松运动的整体水平。 2. 研究对象与方法 本研究选取了一名专业运动员李双锁和一名业余运动员汪红祥...