当前位置:网站首页>你真的懂单例模式么
你真的懂单例模式么
2022-08-02 13:13:00 【厚积薄发ض】
这里讲解单例模式中的懒汉模式和饿汉模式的注意事项及代码实现
目录
单例模式
单例模式就是只能有唯一一个实例
饿汉模式
什么是饿汉模式呢??
从字面理解上,一个饿汉很着急迫不及待的想吃饭.
举个栗子,如果进行读取10个G的文件,要是用饿汉模式就是一次性的将10个G的文件全部加载完成才可以看. ---->很着急 , 迫不及待
饿汉模式从类加载开始就创建出一个实例--->(很早的就创建实例-->立即加载)
代码实现:
//饿汉模式
public class Singleton {
//创建私有静态实例,让类加载时就创建出实例-->饿汉模式
private static Singleton instance = new Singleton();
private Singleton(){
//将构造方法设置为私有,保证其他类不能实例化对象(new实例)
}
//构造方法返回实例
public Singleton getInstance(){
return instance;
}
}
- 将instance利用static->从类加载的时候就创建出一个对象.
- 构造方法设置为私有不能让其他类再次new对象
- 返回实例
懒汉模式
懒汉模式与饿汉模式相反
懒汉模式 很缓慢 ~~ 不急迫~~
还是举个读取文件的栗子~~
还是要读取10个G的文件,懒汉模式是加载屏幕所能容纳的范围,能让用户看到的范围,当翻到下一张的时候,再次进行加载 -->效率很高->用多少~~~加载多少~~~
懒汉模式是 等待需要创建实例时在进行创建--->延迟加载
懒汉模式代码实现:
//实现懒汉模式
public class Singleton {
//1.使用volatile保证内存可见性和禁止指令重排序
//2.先将对象初始化为null,当需要实例化对象时在进行创建
private volatile static Singleton instance = null;
//设置构造方法
private Singleton(){
//私有构造方法,防止其他类实例化对象
}
//获取到实例
//1.使用双重if是为了降低竞争锁的概率
public Singleton getInstance(){
//外层if是用来判断实例有没有初始化好?
//1.如果已经初始化,不需要竞争锁,不进入if,直接往下执行
//2.如果没有初始化尝试竞争锁
if(instance==null){
//使用synchronized原因是
//1.防止多个线程同时创建,将读和写打包成一个原子->保证原子性,让其线程竞争锁
synchronized(Singleton.class){
//里层if: 当线程拿到锁之后,再来判断是否要真正的创建实例
if(instance==null){
instance = new Singleton();//实例化对象
}
}
}
return instance;
}
}
使用懒汉模式要注意三点
- 加锁
- 加上volatile关键字
- 双重if锁定
加锁的目的
因为在创建实例时有写线程在读,有些线程在写,所以很可能导致非原子操作,我们就把读和写打包成1个一个原子-->保证原子性,此时多个线程就要竞争锁
加上volatile关键字的作用
- 保证内存可见性
因为有的线程在读有的线程在写,很有可能编译器将其优化成读取寄存器,使得当一个线程修改,而每次读取时不能读取最新值,所以加上volatile
- 禁止指令重排序
因为要创建实例包含三个操作1.申请内存 2. 在内存上构造出实例 3.将地址赋值给对象的引用
编译器优化时,将2,3顺序颠倒,导致实例化出一个无效的对象,所以加上volatile关键字
双重if的目的
双重if最核心的是降低锁的竞争
里层if是保证实例唯一性,当线程拿到锁之后,判断是否要真正的创建实例,-->只能创建一次
外层if
- 保证是否已经创建好实例,如果已经创建好实例,就已经是线程安全,不要再次加锁,当线程安全时在进行加锁,会导致CPU速率下降,很可能造成堵塞,所以如果已经创建好实例,不用再次加锁已经是线程安全.
- 如果没有创建好实例,就尝试竞争锁
匿名内部类实现单例模式
public class InnerClassSingleton {
private InnerClassSingleton(){
//私有构造方法,防止其他类new对象
}
//创建内部类
private static final class SingletonHolder{
private static final InnerClassSingleton instance = new InnerClassSingleton();
}
//返回实例
public InnerClassSingleton getInstance(){
return SingletonHolder.instance;
}
}
使用枚举来实现单例模式
public enum EnumSingleton {
instance;
public EnumSingleton getInstance(){
return instance;
}
}
边栏推荐
猜你喜欢
k8s之KubeSphere部署有状态数据库中间件服务 mysql、redis、mongo
【C语言】细品分支结构——if-else语句
Enterprise Network Planning Based on Huawei eNSP
“二舅”火了,自媒体短视频“爆火”的基本要素,你知道吗?
Intouch System Platform IDE-1
RISC-V 指令格式和6种基本整数指令
二进制中1的个数
Four seasons of trees realized by svg
【C语言】细品分支结构——switch语句
How to create short images and short videos from the media?How to make the click volume reach 10W?
随机推荐
Set proxy server (Google+IE) "Recommended Collection"
3 ways for OpenFeign to set headers
[b01lers2020]Welcome to Earth-1
this的绑定指向详细解答
PGSQL database to realize the import and export
scrapy框架初识1
方正璞华“劳动人事法律自助咨询服务平台”在武汉武昌区投入使用!
ThinkPHP 5.1反序列化分析和poc
Seata Distributed Transaction
uniapp/小程序 onload方法每次打开页面都执行解读
【C语言】手撕循环结构 —— while语句
微信小程序getPhoneNumber接口code=40013
wx-wow(微信小程序动效库)
Seata分布式事务
冰箱“扩容”的战事,在今夏格外猛烈
Oracle update误操作单表回滚
PHP+MYSQL [Student Information Management System] (Minimalist Edition)
汉源高科千兆12光12电管理型工业以太网交换机 12千兆光12千兆电口宽温环网交换机
基于 WeihanLi.Npoi 实现excel导入时纯汉字的日期转换
为什么IDEA连接mysql Unable to resolve table 编译报错但是可以运行