首页 > 编程语言 >Java中常用的线程安全单例模式实现

Java中常用的线程安全单例模式实现

时间:2024-11-21 10:44:24浏览次数:1  
标签:Singleton Java instance 安全 线程 单例 public 加载

在 Java 中,实现线程安全的单例模式有多种方式。以下是几种常用的线程安全单例模式实现:


1. 饿汉式(线程安全,类加载时初始化)

特点:简单且线程安全,但如果实例过于占用资源且程序可能不使用它,会造成内存浪费。

public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
​
    // 私有构造方法,防止外部创建实例
    private Singleton() {}
​
    // 全局访问点
    public static Singleton getInstance() {
        return INSTANCE;
    }
}
  • 优点:实现简单,类加载时就完成实例化,线程安全。

  • 缺点:即使不使用也会实例化,占用资源。


2. 懒汉式(线程不安全,延迟加载)

特点:实例在需要时创建,但默认实现线程不安全。

public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
​
    // 私有构造方法,防止外部创建实例
    private Singleton() {}
​
    // 全局访问点
    public static Singleton getInstance() {
        return INSTANCE;
    }
}
  • 缺点:在多线程环境中可能会创建多个实例,不推荐在并发场景下使用。


3. 懒汉式 + synchronized(线程安全,但性能较差)

特点:通过 synchronized 关键字确保线程安全,但性能较低。

public class Singleton {
    private static Singleton instance;
​
    private Singleton() {}
​
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
  • 优点:线程安全,延迟加载。

  • 缺点synchronized 会影响性能,每次调用都要获取锁。


4. 双重检查锁(推荐,性能较高)

特点:结合延迟加载与线程安全,减少同步开销。

public class Singleton {
    // 使用 volatile 确保多线程下的可见性和禁止指令重排序
    private static volatile Singleton instance;
​
    private Singleton() {}
​
    public static Singleton getInstance() {
        if (instance == null) { // 第一次检查
            synchronized (Singleton.class) {
                if (instance == null) { // 第二次检查
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
  • 优点:线程安全,延迟加载,性能较好。

  • 缺点:实现稍显复杂。


5. 静态内部类(推荐,线程安全,延迟加载)

特点:利用类加载机制实现延迟加载,同时天然线程安全。

public class Singleton {
    private Singleton() {}
​
    // 静态内部类,在加载时初始化 Singleton 实例
    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }
​
    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}
  • 优点

    1. 延迟加载:Holder 类只有在第一次调用 getInstance 方法时才会加载并初始化实例。

    2. 线程安全:JVM 类加载机制保证线程安全。


6. 枚举单例(最简单,线程安全)

特点:利用枚举的特性实现单例。

public enum Singleton {
    // 定义一个枚举元素,代表 Singleton 的唯一实例
    INSTANCE;

    // 单例类中的其他方法或变量
    private int value;

    // 初始化方法,可以在枚举的构造方法中进行初始化
    Singleton() {
        this.value = 42; // 假设默认值为 42
    }

    // 对外暴露的方法,可以操作或获取内部状态
    public void someMethod() {
        System.out.println("Singleton method invoked. Current value: " + value);
    }

    // Getter 和 Setter 方法
    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}
public class Main {
    public static void main(String[] args) {
        // 获取单例实例
        Singleton instance = Singleton.INSTANCE;

        // 调用方法
        instance.someMethod(); // 输出: Singleton method invoked. Current value: 42

        // 修改状态
        instance.setValue(100);
        System.out.println("Updated value: " + instance.getValue()); // 输出: Updated value: 100
    }
}

  

  • 优点

    1. 线程安全:枚举本身是线程安全的。

    2. 防止反序列化创建新实例:枚举类型保证了单例。

  • 缺点:不能进行懒加载,但推荐作为一种标准单例实现方式。


总结

实现方式是否线程安全是否延迟加载优点缺点
饿汉式 简单,线程安全 不使用时会浪费资源
懒汉式 延迟加载 多线程环境可能不安全
synchronized 懒汉式 简单,线程安全 性能差
双重检查锁 性能较好,线程安全 实现复杂
静态内部类 延迟加载,线程安全,推荐使用 适用性广,缺点少
枚举单例 简洁,线程安全,防反序列化和反射攻击 不能延迟加载

推荐实现

  • 常规场景:使用 静态内部类枚举单例,线程安全且性能优越。

  • 对性能要求极高:可以使用 双重检查锁 实现。

标签:Singleton,Java,instance,安全,线程,单例,public,加载
From: https://www.cnblogs.com/luorongxin/p/18560118

相关文章

  • JavaApi---第一节
    JavaApi高级编程JavaApi什么是JavaApi?JavaApi是一组预先定义好的类和接口,帮助开发者快速开发程序JavaApi就是学会如何使用别人编写的类和接口Api应用程序的接口函数与类的集合实际就是别人写好的类Java中常用的包Java.lang:基础语言包java.util:......
  • java工具类static静态方法读取yml配置
    当我们需要在工具类中获取yml配置的时候,由于变量是staic导致获取不到yml配置因为spring加载静态方法比IOC早,所以不能直接使用@Value注解读取yml配置,读取结果是null。@ComponentpublicclassTestUtil{//使用@Value注解读取yml配置的数据@Value("${test.url}")......
  • 详解线程的三大特性:原子性、可见性和有序性
    在多线程编程中,理解线程的原子性、可见性和有序性是构建正确并发程序的基础。以下是它们的详细解释:1.原子性(Atomicity)定义原子性指的是操作不可被中断,要么全部执行完成,要么完全不执行。特性原子性操作在执行时不会被其他线程干扰。如果多个线程同时访问共享资......
  • 基于Java+SpringBoot的影院订票系统
    关注底部领取源码源码编号:S346源码名称:基于SpringBoot的影院订票系统用户类型:双角色,用户、管理员主要技术:Java、Vue、ElementUl、SpringBoot运行环境:Windows/Mac、JDK1.8及以上运行工具:IDEA/Eclipse数 据 库:MySQL5.7及以上版本数据库表数量:11张表是否有毕业论文......
  • 基于Java+SpringBoot的影院订票系统
    关注底部领取源码源码编号:S346源码名称:基于SpringBoot的影院订票系统用户类型:双角色,用户、管理员主要技术:Java、Vue、ElementUl、SpringBoot运行环境:Windows/Mac、JDK1.8及以上运行工具:IDEA/Eclipse数 据 库:MySQL5.7及以上版本数据库表数量:11张表是否有毕业论文......
  • 【JavaSE】【网络编程】UDP数据报套接字编程
    目录一、网络编程简介二、Socket套接字三、TCP/UDP简介3.1有连接vs无连接3.2可靠传输vs不可靠传输3.3面向字节流vs面向数据报3.4双向工vs单行工四、UDP数据报套接字编程4.1API介绍4.1.1DatagramSocket类4.1.1.1构造方法4.1.1.2主要方法4.1.2DatagramP......
  • Java项目实战II基于微信小程序的课堂助手(开发文档+数据库+源码)
    目录一、前言二、技术介绍三、系统实现四、文档参考五、核心代码六、源码获取全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。一、前言在信息化教学日益普及的今天,如何更高效地辅助课堂学习,成为了教育技术......
  • Java项目实战II基于微信小程序的书橱系统(开发文档+数据库+源码)
    目录一、前言二、技术介绍三、系统实现四、文档参考五、核心代码六、源码获取全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末一、前言随着数字化时代的到来,阅读方式虽日趋多元......
  • Java项目实战II基于微信小程序的高校寻物平台(开发文档+数据库+源码)
    目录一、前言二、技术介绍三、系统实现四、文档参考五、核心代码六、源码获取全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末一、前言在快节奏的校园生活中,物品遗失与寻找成为......
  • Java项目实战II基于微信的设备故障报修管理系统(开发文档+数据库+源码)
    目录一、前言二、技术介绍三、系统实现四、文档参考五、核心代码六、源码获取全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末一、前言在现代企业管理中,设备故障报修的及时性和......