论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
ToB门户
了解全球最新的ToB事件
博客
Blog
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
应用中心
搜索
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
账号登录
立即注册
找回密码
用户名
Email
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
qidao123.com技术社区-IT企服评测·应用市场
»
论坛
›
软件与程序人生
›
后端开发
›
Java
›
单例设计模式
单例设计模式
杀鸡焉用牛刀
论坛元老
|
2023-2-28 17:46:41
|
显示全部楼层
|
阅读模式
楼主
主题
2085
|
帖子
2085
|
积分
6255
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
单例设计模式
单例模式:
定义:某个类在某个系统中只能有一个实例化对象被获取和使用
实现要点: 1.构造器私有
2.含有一个该类的静态变量保存这个唯一实例
3.对外提供获取该实例对象的方式
分类:1.饿汉式 2.懒汉式
下面对这两种单例模式展开分析,进行对比
饿汉式
1.代码实现1(静态常量方式实现)
public class SingleTon{
private static final SingleTon singleTon = new SingleTon();
private SingleTon(){}
public static SingleTon getSingleTon(){
return singleTon;
}
}
2.代码实现2(静态代码块方式实现)
public class SingleTon{
private staic SingleTon;
//在代码块执行时,创建单例对象
static{singleTon = new SingleTon();}
private SingleTon(){}
public static SingleTon getSingleTon(){
return singleTon;}
}`
public class TestSingleTon{
public static void main(Stirng[] args){
SingleTon s1 = SindleTon.getSingleTon;
SingleTon s2 = SindleTon.getSingleTon;
System.out.println(s1 == s2); //true
}
}
3.特点及代码分析
1)私有化构造器
2)在类的内部创建一个类的实例,static
3)私有化对象,通过公共方法调用
4)此方法只能通过类来调用,因为是static的,类的实例也是static的
5)只创建一个对象,不会有线程不安全的情况
6)在类加载是就完成了类实例化,避免了线程同步问题,但没有达到Lazy Loading的效果,如果没有使用过这个对象,会造成内存浪费
7)如何避免这种情况发生呢?可以采用枚举形式实现单例模式
代码块如下:
public enum SingleTon{
INSTANCE;
}`
懒汉式
1.代码实现1(线程不安全方式)
public class SingleTon{
private SingleTon(){}
private static SingleTon singleTon = null;
//当调用方法时,才创建单例对象
public static SingleTon getSingleTon(){
if(singleTon == null){
singleTon = new SingleTon();
}
return singleTon;
}
}
2.代码分析1
1)起到了lazy Loading的作用,即延迟加载对象,但只能在单线程时使用
2)如果早多个线程下,一个线程进入了if(singleTon == null)判断语句时,若满足条件判断且还没来得及继续执行,另一个线程也进入到if(singleTon == null)判断语句,这就会产生多个实例对象,即线程不安全。
3.代码实现2(线程安全方式\双重检查)
public class SingleTon{
private SingleTon(){}
private static SingleTon singleTon = null;
//当调用方法时,才创建单例对象
public static SingleTon getSingleTon(){
if(singleTon == null){//第一层检查,检查是否有引用对象,如果一个线程获取了实例,则不需要进入同步代码块中了
synchronized (SingleTon.class){//第一层锁,保证只有一个线程进入。同步代码块使用的锁是单例的字节码文件对象,且只能用这个锁
if(singleTon == null){ //第二层检查
singleTon = new SingleTon();
}
}
return singleTon;
}
}
4.代码分析2
//volatile关键字的作用为禁止指令重排,保证返回singleTon对象一定在创建对象后
singleTon = new SingleTon();该语句的底层实现逻辑为:
(1)在堆上开辟空间
(2)属性初始化
(3)引用指向对象
//假设以上三个内容为三条单独指令,因指令重排可能会导致执行顺序为1->3->2(正常为1->2->3),当单例模式中存在普通变量需要在构造方法中进行初始化操作时,单线程情况下,顺序重排没有影响;但在多线程情况下,假如线程1执行singleton=new Singleton()语句时先1再3,由于系统调度线程2的原因没来得及执行步骤2,但此时已有引用指向对象也就是singleton!=null,故线程2在第一次检查时不满足条件直接返回singleton,此时singleton为null(即str值为null)
//volatile关键字可保证singleton=new Singleton()语句执行顺序为123,因其为非原子性依旧可能存在系统调度问题(即执行步骤时被打断),但能确保的是只要singleton!=0,就表明一定执行了属性初始化操作;而若在步骤3之前被打断,其他线程可进入第一层检查向下执行创建对象.此时线程2拿到的不是一个null singleton,而是一个没有被步骤2正确初始化的singleton。
5.代码实现3(静态内部类)
//懒汉式:静态内部类形式
public class SingleTon {
private SingleTon(){
}
private static class Inner{
private static final SingleTon SINGLE_TON = new SingleTon();
}
public static SingleTon getSingleTon(){
return Inner.SINGLE_TON;
}
}
//分析:(1)只有在调用方法时,才会加载到内部类,从而完成类的实例化,singleTon。
(2)避免了线程不安全,利用静态内部类特点实现延迟加载,效率高。
6.实际应用
public class LazySingleDesign {
private static LazySingleDesign lazySingleDesign = null ;
private LazySingleDesign(){}
public static LazySingleDesign getInstance(){
synchronized(LazySingleDesign.class){
if(lazySingleDesign == null){
lazySingleDesign = new LazySingleDesign();
}
}
return lazySingleDesign;
}
}
@Testpublic void test() {ExecutorService executor = Executors.newFixedThreadPool(10);for(int i = 0 ; i < 10;i++){executor.execute(new Runnable() {@Overridepublic void run() {LazySingleDesign user = LazySingleDesign.getInstance();System.out.println("design = " + user);}});}}`
getInstance()方法内的第一个if判断可以去掉,生成的也是单例。另外可见性可以去掉也不影响生成的单例。
参考文章链接:1.
https://blog.csdn.net/weixin_42617262/article/details/90448083
2.
https://big-data.blog.csdn.net/article/details/83422780?spm=1001.2101.3001.6650.9&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-9-83422780-blog-115265060.pc_relevant_3mothn_strategy_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-9-83422780-blog-115265060.pc_relevant_3mothn_strategy_recovery&utm_relevant_index=16
3.
https://blog.csdn.net/qq_42804736/article/details/115265060
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复
使用道具
举报
0 个回复
倒序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
回帖后跳转到最后一页
发新帖
回复
杀鸡焉用牛刀
论坛元老
这个人很懒什么都没写!
楼主热帖
ElasticSearch-高级查询
手把手带你通过API创建一个loT边缘应用 ...
一、kotlin基础语法学习
背八股文的都是什么水平
第4章 复合类型
揭秘 ChunJun:如何实现 e2e&session ...
生产事故-记一次特殊的OOM排查 ...
Apache Hudi 在袋鼠云数据湖平台的设计 ...
开源轻量级工作流WorkflowCore介绍 ...
源码解析 Handler 面试宝典
标签云
渠道
国产数据库
集成商
AI
运维
CIO
存储
服务器
快速回复
返回顶部
返回列表