当前位置:网站首页>说说单例模式!
说说单例模式!
2022-06-25 22:06:00 【程の编程日记】
单例模式
定义
确保一个类只有一个实例,并且提供该实例的全局访问点,就是这个类只能被new一次,并且每次都是用的new的这个。
类结构
一个私有的构造方法,一个私有的静态的实例变量,一个公有的静态函数,用来获取实例。
私有构造方法:可以不让别人创建
共有的静态函数:该实例的全局访问点,返回唯一的私有的静态实例变量
具体实现
懒汉式-线程不安全
懒汉式就是用到的时候才创建返回对象,不用到的时候不会创建,但也存在线程不安全的问题
线程不安全:多个线程同时第一次访问获取对象,都判断为空,然后都new了对象,导致多次实例化对象
public class Singleton {
private static Singleton uniqueInstance;
private Singleton(){
}
public static Singleton getUniqueInstance(){
if (uniqueInstance == null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
懒汉式-线程安全
如何解决懒汉式的线程不安全问题呢?使其变为线程安全的,只需要在获取实例的时候加锁就行,这样同一时间只能有一个线程进入获取实例的方法,就可以避免线程不安全问题了!
缺点:由于加锁了,导致同一时间只能有一个线程访问这个方法,有性能问题,不建议使用。
public static synchronized Singleton getUniqueInstance(){
if (uniqueInstance == null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
饿汉式-线程安全
也是为了解决懒汉式的线程不安全问题,直接实例化就行,不再使用延迟实例化,但是没有延迟实例化能节约资源
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton(){
}
public static synchronized Singleton getUniqueInstance(){
return uniqueInstance;
}
}
双重校验锁-线程安全
就是在实例化的时候进行加锁即可,不在方法上进行加锁了
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton(){
}
public static Singleton getUniqueInstance(){
if (uniqueInstance == null){
synchronized (Singleton.class){
if (uniqueInstance == null){
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
首先解释为什么用volatile关键字
禁止jvm的指令重排,首先实例化一个对象分为三个步骤
- 分配内存空间
- 初始化对象
- 将对象指向分配的内存地址
这个顺序在jvm中执行式有可能乱序的,比如会132这样执行,当一个线程执行完成13之后,另一个线程刚好进入if判断不为空,直接就返回了一个未初始化的对象,所以为了解决这个问题使用volatile关键字可以禁止指令重排
再解释为什么用两个if
当两个线程同时进入第一个if,都判断不为空,然后上锁,一个线程进行实例化对象操作,实例化完毕后,另一个线程也加锁进入,但是如果没有第二个if的话,第二个进程还会进行实例化,加上之后就不会进行第二次实例化了。
静态内部类实现-线程安全
就是使用一个静态内部类,类中写一个静态常量,Singleton类被加载的时候并不会调用内部类,只有需要获取实例的时候才会调用内部类进行获取。
实现了延迟实例化+线程安全
public class Singleton {
private Singleton(){
}
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getUniqueInstance(){
return SingletonHolder.INSTANCE;
}
}
边栏推荐
- mysql版本升级+数据迁移
- 提取系统apk
- 对卡巴斯基发现的一个将shellcode写入evenlog的植入物的复现
- Hbuilderx uses the gaude map to obtain the current location
- php中使用Makefile编译protobuf协议文件
- Qlabel text scrolling horizontally
- 第六章 习题(678)【微机原理】【习题】
- C# IO Stream 流(一)基础概念_基本定义
- Analyse des cinq causes profondes de l'échec du développement de produits
- .user.ini文件导致的php网站安装问题
猜你喜欢
随机推荐
Hbuilderx uses the gaude map to obtain the current location
先序线索二叉树
idea Kotlin版本升级
Audio basics and PCM to WAV
Leetcode (605) -- flower planting
A. Balance the Bits--Codeforces Round #712 (Div. 1)
经典图像分割网络:Unet 支持libtorch部署推理【附代码】
OpenResty篇01-入门简介和安装配置
Today's 61 Fu
Kylin
产品经理如何把控产品开发的进度
Reprint: detailed explanation of qtablewidget (style, right-click menu, header collapse, multiple selection, etc.)
phoenix索引
关于Swoole协程容器
C. Yet Another Card Deck-Educational Codeforces Round 107 (Rated for Div. 2)
Anaconda一文入门笔记
使用百度地图API在地图中设置一个覆盖物(InfoWindow),可自定义窗口内容
DPVS-FullNAT模式部署篇
CXF
A. Balance the Bits--Codeforces Round #712 (Div. 1)









