java设计模式(一)——单例模式

一、模式介绍

单例模式:

某一个类在系统中只需要有一个实例对象,而且对象由这个类自行实例化并提供给系统其他地方使用,这个类称为单例类。

使用场景:

1、处理资源访问的冲突

2、从业务概念上有些数据在系统中只应保存一份

特点:

某个类只能有一个实例,即使是在多线程运行环境下;

单例类的实例一定是单例类自身创建,而不是单例类外部用其他方式如new方式创建

单例类只需要提供一个方法想整个系统提供这个实例对象

分类:

单例模式分为饿汉模式和懒汉模式,

懒汉模式的意思就是这个类很懒,只要别人不找它要实例,它都懒得创建。

饿汉模式在初始化时,我们就创建了唯一的实例,即便这个实例后面并不会被使用。

二、代码实现

1、饿汉模式实现

java 复制代码
/**
 * 饿汉模式
 * 使用静态常量在类加载前创建实例,其线程是安全的,有jvm保证其线程安全
 */
public class HungrySingleton {
    private static final HungrySingleton instance = new HungrySingleton();

    //构造函数定义为私有,防止外部创建实例
    private HungrySingleton(){

    }
    // 系统使用单例的入口
    public static HungrySingleton getInstance(){
        return instance;
    }
}

2、懒汉模式实现

2.1、经典懒汉模式
java 复制代码
/**
 * 经典单例模式,只适用于单线程,线程不安全
 */
// 懒汉模式
public class LayzSingleton01 {
    private static LayzSingleton01 instance;

    //构造函数定义为私有,防止外部创建实例
    private LayzSingleton01(){

    }

    //系统使用单例的入口
    public static LayzSingleton01 getInstance(){
        if(instance==null){
            return new LayzSingleton01();
        }
        return instance;
    }
}
2.2、线程安全懒汉模式
java 复制代码
/**
 * 懒汉模式,
 * 添加 synchronized 保证线程安全,单会拖延效率
 * 高并发下多个线程区获取这个实例,需要排队。
 */
// 懒汉模式
public class LayzSingleton02 {

    private static LayzSingleton02 instance;

    //构造函数定义为私有,防止外部创建实例
    private LayzSingleton02(){

    }

    //系统使用单例的入口
    public static synchronized LayzSingleton02 getInstance(){
        if(instance == null){
            return new LayzSingleton02();
        }
        return instance;
    }
    
}
2.3、优化效率懒汉模式
java 复制代码
/**
 * 懒汉模式,添加synchronized代码块解决效率问题,但是此情况还是会出现线程不安全情况
 * 假设我们有两个线程 T1与T2并发访问getInstance方法。
 * 当T1执行完if (instance == null)且instance为null时,其CUP执行时间被T2抢占,所以T1还没有创建实例。
 * T2也执行if (instance == null),此时instance肯定还为null,T2执行创建实例的代码,
 * 当T1再次获得CPU执行时间后,其从synchronized 处恢复,又会创建一个实例。
 */

// 懒汉模式
public class LayzSingleton03 {

    private static LayzSingleton03 instance;

    //构造函数定义为私有,防止外部创建实例
    private LayzSingleton03(){

    }

    //系统使用单例的入口
    public static LayzSingleton03 getInstance(){

        if(instance==null){
            synchronized (LayzSingleton03.class){
                instance = new LayzSingleton03();
            }
        }
        return instance;

    }
}
2.4、double-check懒汉模式
java 复制代码
/**
 * 懒汉模式,double-check 保证线程安全和效率
 * 这种单例的写法做了两次 if (null == instance)的判断,因此被称为double-check的方式。
 * 第一次check为了提高访问性能。因为一旦实例被创建,后面线程的所有的check都为假,不需要执行synchronized竞争锁了。
 * 第二次check是为了线程安全,确保多线程环境下只生成一个实例。
 * 需要注意的是,这种方式,在定义实例时一定需要加上volatile 关键字,禁止虚拟机指令重排,
 * 否则,还是有一定几率会生成多个实例,关于volatile 关键字和指令重排的问题请自行百度,
 */

// 懒汉模式
public class LayzSingleton04 {

    //注意加上volatile关键字
    private static volatile LayzSingleton04 instance;

    //构造函数定义为私有,防止外部创建实例
    private LayzSingleton04(){

    }

    //系统使用单例的入口
    public static LayzSingleton04 getInstance(){

        //第一次检查提高访问性能
        if(instance==null){
            synchronized (LayzSingleton04.class){
                //第二次检查为了线程安全
                if(instance==null){
                    instance = new LayzSingleton04();
                }
            }
        }
        return instance;
    }
}
相关推荐
风味蘑菇干4 分钟前
JDBC(数据库连接池&DBUtils)
java·数据库
Chengbei118 分钟前
CTF & 红队专用 AI 求解AI 引擎 Cairn 系统,化轻量化部署,红队、CTF、漏洞研究一站式解决方案
java·人工智能·安全·web安全·网络安全·系统安全
墨白曦煜9 分钟前
算法实战笔记:空间换时间的黑魔法——单调栈全景解析(十一)
java·笔记·算法
AI玫瑰助手16 分钟前
Python函数:函数的文档字符串(docstring)编写
android·java·python
周末也要写八哥19 分钟前
线程的生命周期之“守护“线程
java·开发语言·jvm
乐之者v21 分钟前
地图技术后端开发的知识点
java
亦暖筑序27 分钟前
Java 8老系统AI工具接入:API包装成受控工具,只读优先+权限拦截
java·人工智能·aigc·企业架构·mcp协议
砍材农夫28 分钟前
物联网实战:Spring Boot + Netty 搭建 MQTT 统一接入层
java·网络·spring boot·后端·物联网·spring
写代码的小阿帆29 分钟前
英语四六级证书审核(SpringBoot+Dify+RPA)
java·spring boot
redaijufeng30 分钟前
我在C++中深入理解了继承,收获颇丰
java·c++·算法