最常考的设计模式之一---单例模式

软件开发中有很多常见的 "问题场景". 针对这些问题场景, 大佬们总结出了一些固定的套路 ,这些套路就被称为设计模式

而我们今天要介绍的就是设计模式中的单例模式


单例模式的定义

单例模式是一种常见的设计模式,它确保一个类只有一个实例,并提供一个全局访问点。这在需要控制资源访问、限制对象数量、或者跨系统访问时非常有用。

单例模式具体的实现方式, 分成 "饿汉" 和**"懒汉"** 两种.

懒汉式单例 :在第一次被调用时创建实例

示例代码如下:

java 复制代码
public class SingleTon {

    //我们要创建的实例instance,因为全局只会存在一个,所以要加上static
    private static SingleTon instance;

    //构造方法要手动设成private的,不然外部可以随意创建实例,违背了一个实例的初衷
    private SingleTon(){}

    //获取instance的方法,如果instance为null就创建一个,所以也要加上static
    public static SingleTon getInstance(){
        if(instance==null){
            instance=new SingleTon();
        }
        return instance;
    }
    //最后返回instance
}

饿汉式单例 :在类加载时就创建实例

示例代码如下:

java 复制代码
public class SingleTon2 {

    我们要创建的实例instance,饿汉模式直接创建
    private static final SingleTon2 instance=new SingleTon2();

    private SingleTon2(){};

    //因为已经创建了,直接返回就行了
    public static SingleTon2 getInstance(){
        return instance;
    }

}

单例模式的安全隐患

上面的懒汉模式的代码在单线程中是没有问题的,但在多线程中就有安全隐患了

首次创建实例 时. 如果在多个线程 中同时调用 getInstance 方法 , 就可能导致 创建出多个实例

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

java 复制代码
package Singleton;

public class SingleTon {

    private static SingleTon instance;

    private SingleTon(){}

    //加上synchronized关键字
    public static synchronized SingleTon getInstance(){
        if(instance==null){
            instance=new SingleTon();
        }
        return instance;
    }

}

不清楚synchronized 的可以参考Java中的监视器锁 (synchronized 关键字)-CSDN博客

当我们加上锁后,线程确实安全了,但我们每次获取instance实例 时,即使用getInstance()方法 时都要加锁 ,明明只有首次创建实例才需要加锁,后面都不需要加锁了,这就造成了很多多余的开销

所以我们改成getInstance()方法内部判断要不要加锁

代码如下:

java 复制代码
public class SingleTon {

    //加上volatile关键字可以让instance每次使用时强制刷新,避免数据没有及时更新
    private static volatile SingleTon instance;

    private SingleTon(){}

    public static SingleTon getInstance(){

        //首先判断instance是不是null,如果是就进入方法
        if(instance==null){

            //注意这里,因为前面的if是没有加锁的,所以可能同时有多个线程进入方法
            synchronized (SingleTon.class){

                //进入锁中,此时因为前面可能有多个线程进入if语句,所以再判断一下
                if(instance==null){
                    instance=new SingleTon();
                }

            }

        }
        return instance;
    }
}

到这里,关于单例模式的讲解就结束了~

相关推荐
索迪迈科技9 小时前
Flink Task线程处理模型:Mailbox
java·大数据·开发语言·数据结构·算法·flink
float_六七13 小时前
IntelliJ IDEA双击Ctrl的妙用
java·ide·intellij-idea
能摆一天是一天14 小时前
JAVA stream().flatMap()
java·windows
颜如玉15 小时前
🤲🏻🤲🏻🤲🏻临时重定向一定要能重定向🤲🏻🤲🏻🤲🏻
java·http·源码
程序员的世界你不懂16 小时前
【Flask】测试平台开发,新增说明书编写和展示功能 第二十三篇
java·前端·数据库
星空寻流年16 小时前
设计模式第一章(建造者模式)
java·设计模式·建造者模式
gb421528717 小时前
java中将租户ID包装为JSQLParser的StringValue表达式对象,JSQLParser指的是?
java·开发语言·python
曾经的三心草17 小时前
Python2-工具安装使用-anaconda-jupyter-PyCharm-Matplotlib
android·java·服务器
蒋星熠17 小时前
Flutter跨平台工程实践与原理透视:从渲染引擎到高质产物
开发语言·python·算法·flutter·设计模式·性能优化·硬件工程
Metaphor69217 小时前
Java 高效处理 Word 文档:查找并替换文本的全面指南
java·经验分享·word