当前位置:网站首页>关于单例模式
关于单例模式
2022-08-08 06:26:00 【写做四月一日的四月一日】
目录
单例模式可以防止重量型对象的反复创建消耗大量资源。
单例模式实现的步骤
1.构造器私有化
2.对外提供一个getInstance()方法来获取这个实例。
单例模式实现的几个方式
饿汉式
饿汉式(静态常量初始化方式)
public class Hunger {
private final static Hunger INSTANCE = new Hunger();
private Hunger(){}
public static Hunger getInstance(){
return INSTANCE;
}
}饿汉式(静态代码块初始化方式)
public class Hunger {
private static final Hunger instance;
static {
instance = new Hunger();
}
private Hunger(){}
public static Hunger getInstance(){
return instance;
}
}
饿汉式单例模式的优点:简单,避免了线程同步问题。
饿汉式单例模式的缺点:可能造成内存浪费。
懒汉式
懒汉式(普通实现方式)
public class Lazy {
private static Lazy instance;
public static Lazy getInstance(){
if (instance == null){
instance = new Lazy();
}
return instance;
}
}这种方式实现了懒加载,避免了内存浪费,但是存在线程同步问题
懒汉式(同步方法实现)
public class Lazy {
private static Lazy instance;
public static synchronized Lazy getInstance(){
if (instance == null){
instance = new Lazy();
}
return instance;
}
}这种方式实现了懒加载,避免了线程同步问题,但是由于使用了同步方法,每次执行该方法都需要执行加锁和解锁操作,效率较低。
双重检查锁(推荐)
public class DoubleCheckLock {
private static volatile DoubleCheckLock instance;
private DoubleCheckLock(){}
public DoubleCheckLock getInstance(){
if (instance == null){
synchronized (DoubleCheckLock.class){
if (instance == null){
instance = new DoubleCheckLock();
}
}
}
return instance;
}
}在加锁操作前判空,如果instance属性已经被new出来了就不需要进入加锁判断,直接返回对象,提高了执行效率。
在加锁操作后判空,避免有多个线程在第一个判空为true后修改instance变量。
对instance变量添加volatile关键字,避免指令重排:new一个对象包括:1.在堆内存开辟空间;2.对对象初始化;3.使变量指向这片空间。2和3两步可能发生指令重排,以132的方式执行,当完成13而2没有完成,就有一个其它线程拿到这个对象并执行操作就有可能发生错误。
静态内部类实现(推荐)
public class StaticInnerClass {
private StaticInnerClass(){}
public static StaticInnerClass getInstance(){
return Inner.instance;
}
public static class Inner{
public static StaticInnerClass instance;
static {
instance = new StaticInnerClass();
}
}
}添加一个静态内部类,在静态内部类中实例化对象。
当外部类被加载时内部类不会被加载,只有调用getInstance()方法时才会加载内部类,并通过内部类的静态代码块对实例化一个对象,实现了懒加载。
类加载是只执行一次的,避免了线程同步问题。
枚举
枚举的实现是单例的
public enum EnumSingle {
INSTANCE;
public static EnumSingle getInstance(){
return INSTANCE;
}
}获取到的EnumSingle.INSTANCE都是同一个对象。
当使用反射实例化有枚举类的时候会报错,可以避免反射对单例模式的破坏。
避免反射对单例模式的破坏
1.添加一个标志位,如果标志位出错则抛出异常
2.在构造器中判断instance是否为空,不为空则抛异常。
边栏推荐
猜你喜欢

神经网络二分类问题范例,神经网络解决分类问题

OSPF动态配置网络环境

P22 美颜相机——引入动态数组,优化重绘

【图形学】10 UnityShader入门(二)

P03 线程安全 synchronized Lock

NVIDIA CUDA Highly Parallel Processor Programming (8): Parallel Mode: Histogram Calculation

在ENSP中配置DHCP服务器

Nine common interfaces for implementing sequence table in C language

C语言实现链表的增删查改以及OJ题讲解

Accelerate CNNs from Three Dimensions: A Comprehensive Pruning Framework详解
随机推荐
CSDN21天学习挑战赛之插入排序
正则表达式入门要点知识总结
VS2015MFC+SQLService版本的选择
Unity_折线图+UI动画
【图形学】 06 四元数(一)
神经网络二分类问题范例,神经网络解决分类问题
神经网络的图像识别技术,神经网络的层数怎么看
NVIDIA CUDA Highly Parallel Processor Programming (8): Parallel Mode: Histogram Calculation
[Unity] 状态机事件流程框架 (一)(C#事件系统,Trigger与Action)
Unity 本地 IIS 服务搭建之文件夹权限配置
Unity_扇形图(饼状图)+ UI动画
有符号数和无符号数参与运算时的问题
深度神经网络主要模型,深度神经网络预测模型
ExecutionEngineException: String conversion error: Illegal byte sequence encounted in the input.
Unity学习笔记 02 —— 更多API
Leetcode topic sharing and explanation
Problem solving about Unity's button event response error triggering UI events
Solved the problem that when VRTK transmission under Unity HDRP, the screen fades in and out, and the visual occlusion cannot be displayed correctly when passing through the wall
[Unity] GPU动画实现(五)——渲染GPU动画
P03 线程安全 synchronized Lock