写点什么

4. 单例模式

作者:下雨了
  • 2022 年 4 月 03 日
  • 本文字数:1084 字

    阅读完需:约 4 分钟

概念及定义

单例模式顾名思义:一个类在系统范围内只有一个实例。该类需要自己创建自己对应的唯一实例。当然这个实例不仅仅是存在于系统内部,还需要向其他实例提供访问自己的自己的入口。在 Spring 中因为容器的存在,大量使用了单例模式,减少了资源消耗。


单例模式的主要思想

如果一个类在系统内使用的频率较高,则保证这个类在系统的生命周期内一直拥有唯一一个实例,减少该类在系统内频繁的创建与销毁对象,减少资源消耗。


单例模式中角色以及职责

  1. Singleton(单例角色类)

单例模式的实现类


单例模式的优缺点

优点:

  1. 减少了高频访问类的对象的创建与销毁,减少资源消耗。

  2. 可以避免对资源的同时占用。

缺点:

  1. 单例模式没有抽象类,很难在 已有的类上进行扩展。

  2. 单例模式在一定程度上违反了单一职责原则。


实现步骤:

  1. 饿汉模式:在类加载的时候就创建对象,后续 getInstance 可以获取对象。

public class HungrySun {
//static 类加载时创建对象。 private final static HungrySun hungrySun = new HungrySun();
private HungrySun(){}
public static synchronized HungrySun getInstance(){ return hungrySun; }}
复制代码

2.懒汉模式:在第一次调用 getInstance 的时候就创建对象,后续 getInstance 可以获取对象。

public class LazySun {
private volatile static LazySun lazySun;
private LazySun(){ }
public static LazySun getInstance(){ //1 //双重检测,避免在二次getInstance的时候执行加类锁操作。 if(lazySun==null){ //类锁,防止多线程下创建多个对象。 synchronized (LazySun.class){ if(lazySun==null){ lazySun = new LazySun(); } } } return lazySun; }}
复制代码

我们这边仔细分析一下代码:


仅仅靠 1 号注释处的操作,是否能保证单例模式的健壮性?


答案是否定的。


因为new LazySun()并不是 atomic 操作。JVM 会会分成三步进行:

  1. 给对象分配内存。

  2. 调用构造方法创建对象。

  3. 返回对象引用。

因为存在指令重排机制,所以如果线程 1 先执行,且执行顺序为 132,在 3 执行结束而 2 还未执行的时机。这时候线程 2 进来了,这时候判断 lazySun 非空,而返回一个没有进行初始化的对象,这时候调用就会出现异常。

要解决这个问题就在 lazySun 变量上加上volatile关键字,来禁止指令重排。


总结:

  1. 单例模式,从始至终通过 getInstance 获取的对象都是同一个。

  2. 单例模式有三个基本特征:

  3. 有且只有私有的构造方法。

  4. 拥有一个本类对象作为私有属性。

  5. 拥有一个 public static 方法,以提供对象的引用。

发布于: 刚刚阅读数: 3
用户头像

下雨了

关注

还未添加个人签名 2021.05.11 加入

还未添加个人简介

评论

发布
暂无评论
4.单例模式_设计模式_下雨了_InfoQ写作平台