设计模式-单例模式(懒汉式)

1. 概念

  • 保证一个类只有一个实例
  • 并为该实例提供一个全局唯一的访问节点

2. 懒汉式-方式一

2.1 代码示例(方式一)

示例
java 复制代码
public class Singleton03 {

    /**
     * 构造器私有化
     */
    private Singleton03() {

    }

    /**
     * 成员变量
     */
    private static Singleton03 INSTANCE;

    /**
     * 对外提供公有的静态方法
     */
    public static Singleton03 getInstance() {
        // 用到才加载
        if (INSTANCE == null) {
            INSTANCE = new Singleton03();
        }
        return INSTANCE;
    }
}
java 复制代码
public class SingletonTest03 {
    public static void main(String[] args) {
        Singleton03 instance = Singleton03.getInstance();
        Singleton03 instance1 = Singleton03.getInstance();
        System.out.println(instance == instance1);
        System.out.println("instance.hashCode= " + instance.hashCode());
        System.out.println("instance1.hashCode= " + instance1.hashCode());
    }
}

2.2 优缺点(方式一)

  1. 起到了Lazy Loading的效果,但是只能在单线程下使用。
  2. 如果在多线程下,一个线程进入了if(singleton==null)判断语句块,还未来得及
    往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以
    在多线程环境下不可使用这种方式。

2.3 结论(方式一)

  • 线程不安全,在实际开发中,不要使用这种方式。

3. 懒汉式-方式二

3.1 代码示例(方式二)

示例
java 复制代码
public class Singleton04 {
    /**
     * 构造器私有化
     */
    private Singleton04() {

    }

    /**
     * 成员变量
     */
    private static Singleton04 INSTANCE;

    /**
     * 对外提供公有的静态方法
     */
    public static synchronized Singleton04 getInstance() {
        // 加入同步代码,解决线程不安全问题
        if (INSTANCE == null) {
            INSTANCE = new Singleton04();
        }
        return INSTANCE;
    }
}
java 复制代码
public class SingletonTest04 {
    public static void main(String[] args) {
        Singleton04 instance = Singleton04.getInstance();
        Singleton04 instance1 = Singleton04.getInstance();
        System.out.println(instance == instance1);
        System.out.println("instance.hashCode= " + instance.hashCode());
        System.out.println("instance1.hashCode= " + instance1.hashCode());
    }
}

3.2 优缺点(方式二)

  1. 解决了线程不安全问题。
  2. 效率太低了,每个线程在想获得类的实例时候,执行getinstance()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面的想想获得该类实例,直接return就行了。方法进行同步效率太低。

3.3 结论(方式二)

  • 线程安全,但效率太低,在实际开发中,不推荐使用这种方式。

4. 懒汉式-方式三

4.1 代码示例(方式三)

示例
java 复制代码
public class Singleton05 {

    private Singleton05() {}

    private static Singleton05 INSTANCE;

    public static Singleton05 getInstance() {
        if (INSTANCE == null) {
            synchronized (Singleton05.class) {
                INSTANCE = new Singleton05();
            }
        }
        return INSTANCE;
    }
}
java 复制代码
public class SingletonTest05 {
    public static void main(String[] args) {
        Singleton05 instance = Singleton05.getInstance();
        Singleton05 instance1 = Singleton05.getInstance();
        System.out.println(instance == instance1);
        System.out.println("instance.hashCode= " + instance.hashCode());
        System.out.println("instance1.hashCode= " + instance1.hashCode());
    }
}

4.2 优缺点(方式三)

  1. 这种方式,本意是想对第四种实现方式的改进,因为前面同步方法效率太低,改为同步产生实例化的的代码块。
  2. 但是这种同步并不能起到线程同步的作用。跟方式一实现方式遇到的情形一致,假如一个线程进入了if(singleton==null)判断语句块,还未来来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。

4.3 结论(方式三)

  • 线程不安全,在实际开发中,不要使用这种方式

相关推荐
非优秀程序员2 小时前
第04章 邮箱大战,163 与 QQ 的暗战|《互联网产品恩仇录》
java·vue.js·架构
知已难寻3 小时前
Docker 入门:容器技术与 Docker 基础
java·运维·服务器·docker·云原生·容器
文丑颜不良啊5 小时前
LeetCode2481~2500题目解析
java·leetcode
Flynn Liang6 小时前
同一需求三套写法:用 Spring AI、LangChain4j、AgentScope Java 各实现一个带工具调用的 RAG 助手(实战对比)
java·人工智能·大模型·架构设计·spring ai·langchain4j·agentscope
聪明的笨猪猪6 小时前
实际工程问题:AI 生成 Spring Cache(@Cacheable / @CachePut / @CacheEvict)缓存注解踩坑
java·经验分享·面试·ai编程
愿有所息7 小时前
记一次 ARM64 + JDK8 上 fastjson2 的诡异数据错乱
java
秋饼7 小时前
MCP 2026-07-28 无状态协议大改版:Spring AI 2.1 多轮往返请求与网关路由落地
java·ai·技术分享·后端开发
SL_staff8 小时前
JVS-BI 实战:业务人员如何用零代码 ELT + 可视化配置构建实时经营分析闭环
java·spring·全栈
SL_staff9 小时前
企业AI落地难?JVS-AI渐进式实践:安全可控、小切口验证、标准化沉淀与规模化复制
java·开源·aigc
SL_staff10 小时前
JVS数字底座实践:构建企业级统一内容管理平台的技术路径
java·产品