当前位置:网站首页>说说单例模式!
说说单例模式!
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;
}
}
边栏推荐
- A. Balance the Bits--Codeforces Round #712 (Div. 1)
- OpenJudge NOI 2.1 15:Counterfeit Dollar
- C. Yet Another Card Deck-Educational Codeforces Round 107 (Rated for Div. 2)
- (serial port Lora module) centrida rf-al42uh private protocol test at instruction test communication process
- Leetcode (605) -- flower planting
- Screen recording to GIF is an easy-to-use gadget, screentogif, which is free and easy to use!
- 期末复习【机器学习】
- 18亿像素火星全景超高清NASA放出,非常震撼
- 如何设计产品的roadmap?
- Run the dronekit flight control application on Shumei faction under px4-jmavsim software simulation environment
猜你喜欢
随机推荐
Uniapp -- list page of multi header tabs
第六章 习题(678)【微机原理】【习题】
Kotlin null pointer bug
.user.ini文件导致的php网站安装问题
Uni app -- listen for the exit of the return key
权限设计=功能权限+数据权限
UE4 learning record 2 adding skeleton, skin and motion animation to characters
为什么Integer的比较最好使用equals
Graduation trip | recommended 5-day trip to London
C. Fibonacci Words-April Fools Day Contest 2021
CSDN force value
中序线索二叉树
The package name of the manifest file in the library project and the app project are not the same
Megacli常用命令整理
流数据
Qlabel text scrolling horizontally
InputStream流已经关闭了,但是依旧无法delete文件或者文件夹,提示被JVM占用等
对卡巴斯基发现的一个将shellcode写入evenlog的植入物的复现
mysql版本升级+数据迁移
mysql5.7版本在配置文件my.ini[mysqld]加上skip-grant-tables后无法启动