剑指offer第二版面试题2:实现Singleton模式(java)

当前位置: 钓虾网 > 圈子 > 剑指offer第二版面试题2:实现Singleton模式(java)

剑指offer第二版面试题2:实现Singleton模式(java)

2024-11-06 作者:钓虾网 1

---

剑指offer第二版面试题2:实现Singleton模式(java)

设计单例类:一生只此一例

我们面临一个特别的挑战:设计一个类,它只允许我们生成一个实例。这样的类是单例模式的典型代表。让我们揭开这一模式的神秘面纱。

进入“懒汉式单例”的世界。这里的策略是:在第一次被调用时才会进行实例化。听起来颇为优雅,但其实现方式在不同环境下有所不同。

单线程环境下的单例模式

设想一个环境,只有一条线程在运行。我们的类设计如下:将构造函数设为私有,确保外部无法直接创建实例。然后,提供一个静态的`getInstance`方法,内部判断是否已经存在实例,如果没有则创建。

```java

public class Singleton {

private static Singleton instance = null; // 静态实例,默认null

// 私有构造函数,防止外部创建实例

private Singleton() {}

// 获取唯一实例的方法

public static Singleton getInstance() {

if (instance == null) { // 第一次检查实例是否存在

instance = new Singleton(); // 创建实例

}

return instance; // 返回唯一实例

}

... // 其他方法和属性

}

``` 当你运行`main`函数,即使连续多次调用`getInstance()`方法,都会得到同一个实例的引用。这就是单例的魅力所在。但这种方法在多线程环境下会有问题。两个线程可能同时检测到`instance`为null并尝试创建实例,导致出现多个实例。这违背了单例模式的初衷。

多线程环境下的懒汉式单例模式

为了在多线程环境中保持单例的唯一性,我们可以为`getInstance()`方法加上同步锁(synchronized)。但这样每次调用都会进行加锁操作,效率低下且可能造成线程阻塞。为此我们引入更为高效的双重检查锁定机制。这一机制在第一次实例化时进行同步加锁处理,并在加锁内部再次检查实例是否已经存在。这样既能确保单例的唯一性,又能减少不必要的同步开销。这种策略在并发环境下表现得尤为出色。以下是双重检查加锁的示例代码:

```java

饿汉式与懒汉式单例模式的探索与比较

在编程中,单例模式是一种常见的设计模式,它确保一个类只有一个实例,并提供一个全局访问点。现在我们来探讨其中的两种实现方式:饿汉式和懒汉式,并从线程安全、资源加载和性能等方面进行深度比较。

3.4 使用静态内部类实现的懒汉式单例模式

这种懒汉式单例模式在实例创建时采用了双重检查锁定机制,确保了线程安全,同时避免了不必要的同步,提升了性能。这种模式在第一次调用 `getInstance()` 方法时才会实例化对象,实现了延迟加载。

代码示例:

```java

public class Singleton {

// 构造函数设计为私有的,以禁止在其他类中创建实例

private Singleton() {}

// 静态内部类实现延迟加载和线程安全

private static class LazyHolder {

private static final Singleton INSTANCE = new Singleton();

}

public static Singleton getInstance() {

return LazyHolder.INSTANCE;

}

}

```

饿汉式单例类

饿汉式单例类在类初始化时就已经完成了实例的创建,因此它是线程安全的,无需额外的同步措施。这种模式在类加载时就完成了实例的创建,之后不再改变。

代码示例:

```java

public class Singleton1 {

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

private static final Singleton1 single = new Singleton1(); // 类加载时完成实例化

public static Singleton1 getInstance() { return single; } // 提供全局访问点

}

```

饿汉式与懒汉式的比较

线程安全:饿汉式单例由于其天生特性,是线程安全的。而懒汉式单例则需要采取额外的措施(如双重检查锁定)来实现线程安全。在并发环境下,懒汉式如果不加同步处理可能会出现问题。在多线程环境下使用单例模式时,推荐使用饿汉式或经过同步处理的懒汉式实现。

资源加载和性能:饿汉式单例在类加载时就完成了实例的创建,无论后续是否使用这个实例都会占用一定的内存资源。但相应的,它在第一次调用时速度更快,因为资源已经初始化完成。懒汉式单例则实现了延迟加载,第一次使用时才会创建实例。因此第一次调用时会有一定的初始化开销,但之后就和饿汉式一样了。在资源使用和性能之间需要根据实际需求进行权衡。对于内存充足且追求首次调用性能的场景,可以选择饿汉式;对于内存敏感的场景,可以考虑懒汉式实现延迟加载。总体而言,这两种方式各有优劣,需要根据具体需求进行选择。

文章来自《钓虾网小编|www.jnqjk.cn》整理于网络,文章内容不代表本站立场,转载请注明出处。

本文链接:https://www.jnqjk.cn/quanzi/164170.html

AI推荐

Copyright 2024 © 钓虾网 XML

蜀ICP备2022021333号-1