文档章节

【创建型】- 单例模式

ZeroneLove
 ZeroneLove
发布于 02/19 23:02
字数 1030
阅读 11
收藏 0

单例模式


单例模式客户端每次访问都只返回相同的对象

思路


  • 类在进行初始化时创建静态对象,因静态对象从属于类本身,每次客户端访问都将返回相同的静态对象(饿汉模式)

  • 当客户端需要的时创建,客户端多次访问的时候判断非空,如果存在则返回之前创建的对象,如果不存在则创建新的对象,对象内部维持一个对第一次创建对象的引用(懒汉模式:线程不安全)


饿汉模式:对象加载时创建,每次返回静态对象

package com.zhiwei.singleton;

public class SingletonEargerly {

    /**
        * 私有化单例对象的默认构造方法,外部不能创建对象
        */
    private SingletonEargerly(){
        
    }

    private  static SingletonEargerly singletonObject = new SingletonEargerly();

    /**
    * 提供外部的单例对象的访问接口
    */ 
    public static SingletonEargerly getSingletonObject(){
        return singletonObject;
    }

    public  void show(){
        System.out.println("饿汉模式:"+this);
    }
}

分析:因饿汉模式singletonObject 为static类型,SingletonEargerly被JVM加载时,singletonObject 就会被实例化,存放在静态代码区,因此SingletonEargerly访问getSingletonObject()得到对象是唯一的


懒汉模式:对象创建比较懒惰,需要时再创建,类似spring懒加载机制

public class SingletonLazily {
  
    private static SingletonLazily singleton = null;

    private SingletonLazily(){  
    }


    public static SingletonLazily getInstance(){
        
        if(null == singleton){  
            singleton=new SingletonLazily();
        }
        return singleton;
    }
    public void show(){
        System.out.println(Thread.currentThread().getName()+"懒汉模式:"+this);
    }

分析

通过"null == singleton" if语句判断当前的对象是否存在,因第一次使用getInstance()方法返回的是创建的对象,第二次访问由于if判断的关系,因此每次都是返回第一次创建的对象


懒汉模式缺陷:线程不安全

    if (null == singleton){  
            singleton=new SingletonLazily();
        }

分析:假设存在2个线程A、B,当AB两个线程同时访问getInstance()方法时,A线程刚好访问通过if (null == singleton) 语句块cpu中断,OS保存A线程当前状态,线程切换到B,B直接将整个if语句块完整执行,因此创建1个单例对象,B执行完之后OS调度cpu,A线程恢复继续执行,因为之前执行就已经跳过了if语句块,因此A线程就会再创建1个对象,因此AB两个线程分别创建两个对象,造成线程不安全的情况

懒汉模式解决线程不安全的方案


方法整体加同步锁(锁粒度较大,损耗性能较大)

public synchronized static  SingletonLazily getInstanceSafely(){
		
		if(null == singleton){  
			singleton=new SingletonLazily();
		}
		return singleton;
	}

方法内部加锁,减少锁粒度

public static  SingletonLazily safelyGetInstance(){
			
        if(null == singleton){  
            synchronized(singleton){  
                if(null == singleton){  
                    singleton = new SingletonLazily();
                }
            }
        }
        return singleton;
    }

注意:双重检查锁判断

分析:当AB两个线程同时进入第一个if语句块,因为synchronized同步锁的问题,加入A线程首先进入同步代码块,然后创建对象,这个过程线程B被阻塞,如果同步代码块内部代码块不加判断,那么A线程执行完同步代码块后,B进入同步代码块一样会创建新的对象,因此无法避免线程安全的问题,因此这里需要两个if判断

双重检查锁缺陷

当线程A创建完对象后,A线程可能还没完成数据从线程私有空间到主线程内存空间同步,导致B线程仍然判断为空,从而导致B创建新的对象

解决方案:单例对象用volatile修饰,保证对象内存可见性,这样A创建完成后会自动同步到主线程内存空间,B判断的时候从主线程内存同步数据,则判断非空,无需创建新对象

© 著作权归作者所有

共有 人打赏支持
ZeroneLove
粉丝 3
博文 156
码字总数 124333
作品 0
深圳
高级程序员
私信 提问
【设计模式笔记】(十六)- 代理模式

一、简述 代理模式(Proxy Pattern),为其他对象提供一个代理,并由代理对象控制原有对象的引用;也称为委托模式。 其实代理模式无论是在日常开发还是设计模式中,基本随处可见,中介者模式中...

MrTrying
2018/06/24
0
0
设计模式已经陨落了?

你现在是坐在一个程序员旁边吗?如果是的话,那么在你读下面的段落之前,有一个简单的实验。让他们到一边去,问问他们两个问题并记录下答案。首先问他们“什么是设计模式?”然后再问“说出你...

oschina
2014/03/11
9.1K
69
《PHP设计模式大全》系列分享专栏

《PHP设计模式大全》已整理成PDF文档,点击可直接下载至本地查阅 https://www.webfalse.com/read/201739.html 文章 php设计模式介绍之编程惯用法第1/3页 php设计模式介绍之值对象模式第1/5页...

kaixin_code
2018/11/06
0
0
设计模式梳理(一)

设计模式梳理(一) 总体来说设计模式分为三大类: @案例源码地址:https://gitlab.com/lxqxsyu/DisgnPattern 创建型模式 简单工厂模式 工厂类是整个模式的关键。它包含必要的判断逻辑,能够...

lxq_xsyu
2017/11/02
0
0
《JavaScript设计模式与开发实践》原则篇(2)—— 最少知识原则

最少知识原则(LKP)说的是一个软件实体应当尽可能少地与其他实体发生相互作用。这 里的软件实体是一个广义的概念,不仅包括对象,还包括系统、类、模块、函数、变量等。 单一职责原则指导我们...

嗨呀豆豆呢
2018/12/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

前嗅ForeSpider脚本教程:标准对象(一)

今天,小编主要为大家介绍一下:前嗅ForeSpider脚本中的标准对象:爬虫链接类url,urltext采集的所有状态及属性类,html标签节点类domItem和(html)dom类dom。具体内容如下: 一.爬虫链接类...

forespider
10分钟前
1
0
javax.net.ssl.SSLException: closing inbound before receiving peer's close_notify

在使用spring boot整合jpa时出现上述错误,在配置文件中,配置连接数据库的url时,加上useSSL=false url: jdbc:mysql://127.0.0.1:3306/数据库名称?serverTimezone=Asia/Shanghai&useSSL=fa...

朝如青丝暮成雪
20分钟前
1
0
JavaScript 为什么要有 Symbol 类型?

摘要: 为什么比怎么用更有意义。 原文:JavaScript 为什么要有 Symbol 类型 作者:前端小智 Symbols 是 ES6 引入了一个新的数据类型 ,它为 JS 带来了一些好处,尤其是对象属性时。 但是,它...

Fundebug
22分钟前
0
0
vs code 配置.json文件引入makefile文件实现多文件编译

背景: 之前使用VS code写c++时,没使用到多文件,所以对launch.jason和task.jason配置没过多配置,但不支持多文件间的编译,调试。 注:主要针对较大的一些工程,涉及多个文件的编译,使用到...

shzwork
22分钟前
1
0
大神教你Nginx常用基础配置方案

Nginx的fastcgi模块参数设置 Nginx 有两个配置文件fastcgi_params、fastcgi.conf,两者唯一的区别是,fastcgi.conf 多一个参数 SCRIPT_FILENAME,diff显示如下: $diff fastcgi fastcgi_param...

Linux就该这么学
28分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部