如何自己实现一个单例模式,手撕java设计模式

本文详细介绍了Java中的四种单例模式实现,包括懒汉式(线程不安全与线程安全)、双重检查锁定(更优的线程安全版本)和饿汉式(静态初始化)。重点讲解了双重检查锁定如何提高性能并确保线程安全。
摘要由CSDN通过智能技术生成


在Java中,单例模式(Singleton Pattern)保证一个类仅有一个实例,并提供全局访问点。这里展示两种常见的实现单例模式的方式:懒汉式(懒加载)和饿汉式(静态初始化)。

1.懒汉式(线程不安全)

这个版本的懒汉式单例在多线程环境下并不安全,可能会创建多个实例。

public class Singleton {
    private static volatile Singleton instance;

    // 防止通过构造函数直接创建对象
    private Singleton() {}

   public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();  // 这里在多线程环境下可能导致多个实例被创建
        }
        return instance;
    }
}

2.懒汉式(线程安全,使用同步方法)

在这个版本中,我们添加了synchronized关键字来确保多线程环境下的安全性,但这样会影响性能,因为每次调用getInstance()都会进行同步锁操作。

public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {}

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

3.双重检查锁定(线程安全,更优)

双重检查锁定既保证了线程安全,又尽可能地减少了同步的开销。只有在实例未创建时才进行同步,创建后就不再需要同步,提高了效率。

public class Singleton {
    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;
    }
}

4. 饿汉式(静态初始化,线程安全)

饿汉式的实现方式是在类加载时立即创建并初始化单例实例,因此天生就是线程安全的,但无法做到按需加载(lazy initialization)。

public class Singleton {
    // 类加载时即初始化实例,保证线程安全
    private static final Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
   }
}

以下是第三种实现方式——双重检查锁定(Double-Checked Locking)的Java单例模式代码解释:

public class Singleton {
    // 使用volatile关键字确保多线程环境下的可见性和有序性
   private static volatile Singleton instance;

    // 私有化构造函数以防止外部实例化
    private Singleton() {}

    // 提供获取实例的方法
    public static Singleton getInstance() {
        // 第一次检查:如果instance已非空,则直接返回
       if (instance == null) { 
            // 否则同步块内进行第二次检查,并创建实例
            synchronized (Singleton.class) {
               // 在同步块内部再次检查实例是否已经被其他线程创建过
                if (instance == null) {  
                    // 如果未被创建,则创建并初始化
                    instance = new Singleton();
               }
            }
        }
        return instance;
    }
}

这段代码的工作原理是这样的:

  • 当调用 getInstance() 方法时,首先会进行一个非同步的检查,查看 instance 是否已经初始化。如果已经初始化,则直接返回该实例,无需进入同步块。
  • 如果第一次检查发现 instance 为 null,那么代码进入 synchronized 块,在这里进行第二次检查。这是因为在多线程环境下,可能有多个线程同时发现 instance 为空并尝试创建实例,所以需要通过锁来保证只有一个线程能够执行初始化操作。
  • 只有在 instance 确实为空的情况下,才会在同步块中创建并初始化 Singleton 类的一个新实例。
  • 由于两次检查的存在,可以避免每次调用 getInstance() 方法都进行不必要的同步操作,从而提高了性能。

    通过这种方式,我们既保证了单例对象在多线程环境下的唯一性,又尽可能减少了使用同步操作带来的性能开销。
  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
华为OD_java代码题主要是指在面试中华为有可能会出现代码的考核环节。代码是一种常见的面试方式,用来评估应聘者的编程能力和解决问题的能力。 在华为OD_java代码题中,一般会给出一个具体的问题或需求,要求应聘者用Java语言编写出解决该问题的代码。 对于应聘者而言,需要在规定的时间内独立思考并编写代码。这个过程主要考察应聘者的编程思维能力、分析解决问题的能力、代码实现的能力以及解决问题的效率等方面。 虽然具体题目可能会有所不同,但是考察的核心点通常包括:对问题的理解和分析能力、编程语言的熟练度、算法和数据结构的应用能力、代码的易读性和可维护性等。 华为OD_java代码提是一个重要的环节,对于应聘者而言,需要提前准备,熟悉和掌握常见的编程题目和解题思路。在面试过程中,应聘者可以通过合理的思考逻辑、编写简洁高效的代码、充分运用算法与数据结构等方法来提升自己的表现。同时,沟通能力、团队协作能力以及问题解决思路的清晰度和逻辑性也是面试过程中需要注意的要点。 总而言之,华为OD_java代码提是一个重要的筛选环节,对于应聘者来说是一次展示自己编程能力的机会。通过充分准备和积极参与,应聘者可以提高在面试中的表现,增加获得工作机会的可能性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值