当前位置: 首页 > article >正文

设计模式—创建型模式之单例模式

设计模式—创建型模式之单例模式

介绍

单例模式说明:一个单一的类,负责创建自己的对象,同时确保系统中只有单个对象被创建。

单例模式特点:

  1. 某个类只能有一个实例;(构造器私有)
  2. 它必须自行创建这个实例;(自己编写实例化逻辑)
  3. 它必须自行向整个系统提供这个实例;(对外提供实例化方法)

单例模式图示如下:

单例模式图

饿汉式

饿汉式,比较简单,代码如下:

public class SingletonObject {
    private final static SingletonObject obj = new SingletonObject();
    private SingletonObject() {
        System.out.println("创建了单例对象");
    }
    public static SingletonObject getInstance() {
        return obj;
    }
}

懒汉式—效率低下实现方式1(线程安全)

获取实例的方法是static的,我们可以给整个方法加一个锁,这样锁的对象是整个类,可以保证线程安全:

代码实现如下:

public class SingletonObject {
	//懒汉式
	private static SingletonObject obj;
	//保证构造器私有,外部不能实例化
	private SingletonObject() {
		System.out.println("创建了单例对象");
	}
	//这种锁粒度太大,导致效率低
	public static synchronized SingletonObject getInstance() {
		//懒汉式,如果没有再去创建
		if(obj == null) {
			obj = new SingletonObject();
		}
		return obj;
	}
}

懒汉式—效率低下实现方式2(线程安全)

我们可以不给整个方法加锁,可以给如下代码块加锁,但是这样的方式效率还是低;

public class SingletonObject {
	//懒汉式
	private static SingletonObject obj;
	//保证构造器私有,外部不能实例化
	private SingletonObject() {
		System.out.println("创建了单例对象");
	}
	//但是这样锁粒度还是太大,进入到方法里边再加锁,这样效率还低
	public static SingletonObject getInstance() {
		synchronized(SingletonObject.class) {
			//懒汉式,如果没有再去创建
			if(obj == null) {
				obj = new SingletonObject();
			}
		}
		return obj;
	}
}

懒汉式—线程不安全

我们能否在创建时再加锁呢,于是有了如下的代码:

public class SingletonObject {
	//懒汉式
	private static SingletonObject obj;
	//保证构造器私有,外部不能实例化
	private SingletonObject() {
		System.out.println("创建了单例对象");
	}
	//线程不安全
	public static SingletonObject getInstance() {
		//懒汉式,如果没有再去创建
		if(obj == null) {
			synchronized(SingletonObject.class) {
				obj = new SingletonObject();
			}
		}
		return obj;
	}
}

这样的方式是线程不安全的,比如:

  1. 有两个线程,线程1和线程2都进入到方法中,判断到obj为null;
  2. 假如线程1先获取到锁,为obj赋值完成,然后方法运行结束,返回obj;
  3. 然后线程2获取到锁,又把obj赋值一次;此时两次返回的就不是同一个对象了。

懒汉式—双重检查锁

下面的懒汉式设计模式,用了双重检查锁;

public class SingletonObject {
    //懒汉式,线程可见性
    private volatile static SingletonObject obj;
    //首先保证构造器私有,外部不能实例化

    private SingletonObject() {
        System.out.println("创建了单例对象");
    }
    /**
     * 双重检查锁 + 内存可见性volatile
     */
    public static SingletonObject getInstance() {
        //懒汉式,如果没有再去创建
        if (obj == null) {
            synchronized (SingletonObject.class) {
                if(obj == null){
                    obj = new SingletonObject();
                }
            }
        }
        return obj;
    }
}

方法getInstance()中,如果单例对象为空,才会把方法块加锁,获取到锁的线程创建对象完成并赋值成功,且obj保证了线程可见性,其他线程便可以感知到obj不为null,就不会再创建赋值了。


http://www.kler.cn/a/106116.html

相关文章:

  • stm32下的ADC转换(江科协 HAL版)
  • 【分布式】万字图文解析——深入七大分布式事务解决方案
  • stdin文件流指针
  • 文心一言编写小球反弹程序并优化
  • SQL Server 查询设置 - LIKE/DISTINCT/HAVING/排序
  • 职场汇报技巧:选择合适的汇报形式与提供数据依据
  • 分布式日志和链路追踪
  • 【Linux】MAC帧协议 + ARP协议
  • Painter:使用视觉提示来引导网络推理
  • 图的应用4.0-----关键路径(AOE网)
  • 国际腾讯云直播推流配置教程!
  • Elasticsearch(十五)搜索---搜索匹配功能⑥--基于地理位置查询
  • C语言数据结构---时间复杂度、空间复杂度
  • 搭建自己的搜索引擎——oh-my-search使用
  • Linux内存管理(五十九):内存检测工具 kfence(2)
  • c语言进制的转换10进制转换16进制
  • npm i 报错或者卡顿 range manifest for 解决
  • 如何在spark中使用scikit-learn和tensorflow等第三方python包
  • ASO优化之关于Google Play中的搜索引擎优化
  • SQL server数据库单用户模式如何退出
  • c++ 并发与多线程(12)线程安全的单例模式-2
  • Spring | Spring Cache 缓存框架
  • 将CSDN或Confluence文章转为微信公众号格式
  • torch VS tensorflow 同功能的api
  • Flutter和SwiftUI比较
  • 目标跟踪ZoomTrack: Target-aware Non-uniform Resizing for Efficient Visual Tracking