JavaEE之线程(7)_单例模式(设计模式概念、单例模式优点、懒汉、饿汉模式)

一、什么是设计模式?

单例模式是设计模式中较为常见的一种。那么,什么是单例模式?

  1. 设计模式(Design Pattern)都是一些相对优秀的解决方案,很多问题都是典型的、有代表性的问题,学习设计模式,我们就不用自己从头来解决这些问题,相当于在巨人的肩膀上,复用这些方案即可。
  2. 设计模式已经成为专业人士的常用词汇,不懂不利于交流。
  3. 能让你设计的系统更加专业,让系统有更好的架构。

目的:使用设计模式是为了可重用性代码,让代码更容易被他人理解,保证代码可靠性。


二、单例模式

基本概念:
 单例模式是一种设计模式,它的目的是保证一个类只有一个实例,并提供一个全局的访问点。使用单例模式可以避免多次创建对象,节省内存空间,同时也可以保证数据的一致性。

约定某个类,只能有唯一个对象。通过编码技巧,让编译器进行强制检査,(在类里面提前把对象创建好,并且把构造方法设为 private)

2.1 单例模式的好处

  • [ 节省系统资源] :在系统中,如果有多个实例会造成资源浪费,而使用单例模式可以减少这种浪费。
  • [简化了对象访问] :单例模式提供了一个全局的访问点,因此可以简化访问过程。

2.2 懒汉模式

懒汉式单例模式:

在第一次使用时才创建单例对象。缺点是需要考虑线程安全问题。
单线程版代码实例:

//类加载的时候不创建实例. 第一次使用的时候才创建实例.
class Singleton {
	private static Singleton instance = new Singleton();
	private Singleton() {}
	
	public static Singleton getInstance() {
		return instance;
	}
}

 上述代码懒汉模式的实现是线程不安全的

  1. 线程安全问题发生在首次创建实例时。如果在多个线程中同时调用 getInstance 方法,就可能导致创建出多个实例;
  2. 一旦实例已经创建好了, 后面再多线程环境调用 getInstance 就不再有线程安全问题了(不再修改instance 了)

懒汉模式-多线程版

加上 synchronized 可以改善这里的线程安全问题

class Singleton {
	private static Singleton instance = null;
	private Singleton() {}
	public synchronized static Singleton getInstance() {
		if (instance == null) {
			instance = new Singleton();
		}
		return instance;
	}
}

懒汉模式-多线程版(改进版)

代码在加锁的基础上, 做出了进一步改动:

  1. 使用双重 if 判定, 降低锁竞争的频率.。
  2. 给 instance 加上了 volatile。
package single;

/**
 * @author Zhang
 * @date 2024/5/717:12
 * @Description:
 */

class  SingletonLazy{
    private  static volatile  SingletonLazy instance = null;    //懒汉模式

    public  static SingletonLazy getInstance(){

        if(instance == null){
            //如果对象已经有了,线程就安全了,此时就可以不加锁了
            //如果对象还没有,存在在线程不安全的风险,就需要加锁

            synchronized (SingletonLazy.class){  //一旦加锁,就可能产生阻塞
                if (instance == null){   //判定是否要new一个对象
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }
    private  SingletonLazy(){ }

}

public class Test2 {


    public static void main(String[] args) {

    }
}

注意理解上述代码双重 if 判定 / volatile:

  1. 理解双重 if 判定 / volatile:加锁 / 解锁是一件开销比较高的事情。 而懒汉模式的线程不安全只是发生在首次创建实例的时候,因此后续使用的时候, 不必再进行加锁了。
  2. 外层的 if 就是判定下看当前是否已经把 instance 实例创建出来了。同时为了避免 “内存可见性” 导致读取的 instance 出现偏差, 于是补充上 volatile。

2.3 饿汉模式

饿汉式单例模式:在类加载时创建单例对象。缺点是不支持延迟加载。

  1. 优点:单例只有在使用时才被实例化,一定程度上节约了资源 ;
  2. 缺点:加入synchronized关键字,造成不必要的同步开销。不建议使用。
package single;

/**
 * @author Zhang
 * @date 2024/5/716:58
 * @Description:
 */

class  Singleton{
    /**
     * 1. 在类的内部,提供一个现成的实例
     * 2. 把构造方法设置为private,避免其他代码能够创建出实例
     * 通过上述方式,就强制了其他程序员在使用这个类的时候,就不会创建出多个对象了
     */
    private static  Singleton instance  = new Singleton();    //这里的创建时机,是在类加载的时候(比较早的时机)--饿汉模式

   //通过这个方法来获取刚刚的实例
    //后续如果想使用这个类的实例,都通过getInstance() 方法来获取
    public static Singleton getInstance(){
        return instance;
    }

    //把构造方法设置为私有,此时类外面的代码,就无法new相互这个类的对象了
    private Singleton(){ }

}

public class Test1 {

    public static void main(String[] args) {
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        System.out.println(s1 == s2); //true
    }
}

2.4 单例模式的总结

 我们只介绍单例实现方式的饿汉模式、懒汉模式两种方式,其他单例模式的内容可以通过网络资源进行查阅。接下来让我们总结一下不同单例模式的区别:
在这里插入图片描述

总结

 以上就是今天要讲的内容,本文仅仅简单介绍了设计模式的概念,什么是单例模式?包括懒汉模式和饿汉模式,并写出了相应的参考代码。最后,对不同实现方式的单例模式进行了总结。

  • 33
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值