当前位置: 首页 > article >正文

单例模式5种写法

单例模式是设计模式中最简单的一种,其目的是确保一个类只有一个实例,并提供一个全局访问点。以下是单例模式的五种常见写法:

### 一、懒汉式(线程不安全)

```java
public class Singleton {
    private static Singleton instance;

    private Singleton() {}

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

**原理**:
- `instance`变量用于存储唯一的实例,初始值为`null`。
- 构造方法`private`修饰,防止外部通过`new`关键字创建实例。
- `getInstance()`方法用于获取实例。首次调用时,`instance`为`null`,会创建一个新实例并赋值给`instance`,之后再次调用`getInstance()`时,直接返回已创建的实例。

**缺点**:
- 在多线程环境下,可能会出现多个线程同时进入`if (instance == null)`判断,导致创建多个实例。


### 二、懒汉式(线程安全,同步方法)

```java
public class Singleton {
    private static Singleton instance;

    private Singleton() {}

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

**原理**:
- 在`getInstance()`方法上加上`synchronized`关键字,使该方法在多线程环境下是线程安全的。
- 当多个线程同时调用`getInstance()`时,只有一个线程能进入该方法,其他线程会等待当前线程执行完后再进入,从而保证了实例的唯一性。

**缺点**:
- 使用`synchronized`修饰方法会导致性能下降,因为每次调用`getInstance()`方法都会进行同步,即使实例已经被创建。


### 三、懒汉式(线程安全,同步代码块)

```java
public class Singleton {
    private static Singleton instance;

    private Singleton() {}

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

**原理**:
- 使用同步代码块代替同步方法,只对实例创建部分的代码进行同步。
- 第一次检查`instance`是否为`null`,如果不为`null`,直接返回实例,避免了不必要的同步。
- 如果`instance`为`null`,进入同步代码块,再次检查`instance`是否为`null`,如果仍为`null`,则创建实例。这称为双重检查锁定(Double - Check - Locking,DCL)。

**优点**:
- 在保证线程安全的同时,提高了性能,因为只有在实例未被创建时才会进行同步。


### 四、饿汉式

```java
public class Singleton {
    private static final Singleton instance = new Singleton();

    private Singleton() {}

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

**原理**:
- 在类加载时就创建实例,`instance`变量被`final`修饰,保证了其不可变性。
- 构造方法`private`修饰,防止外部创建实例。
- `getInstance()`方法直接返回已创建的实例。

**优点**:
- 实现简单,线程安全,因为类加载是线程安全的,所以实例的创建也是线程安全的。

**缺点**:
- 缺乏懒加载特性,不管是否使用该实例,都会在类加载时创建,可能会造成不必要的资源浪费。


### 五、静态内部类

```java
public class Singleton {
    private Singleton() {}

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
```

**原理**:
- 使用一个静态内部类`SingletonHolder`来持有单例实例。
- 外部类的构造方法`private`修饰,防止外部创建实例。
- `getInstance()`方法返回`SingletonHolder`类中的`INSTANCE`实例。
- 静态内部类在第一次被使用时才会被加载,因此具有懒加载特性,且由于类加载是线程安全的,所以这种方式也是线程安全的。

**优点**:
- 兼具懒加载和线程安全的优点,是单例模式的一种优雅实现方式。
 


http://www.kler.cn/a/500307.html

相关文章:

  • 大语言模型训练的数据集从哪里来?
  • 网易云音乐登录两部手机:IP属地归属何方?
  • mysql根据表的统计信息核算一下表成本
  • Elasticsearch入门篇
  • 丢帧常见的几种处理方法
  • python+pdfplumber:提取和分析PDF中的表格、文本等数据,实现pdf转图片、CSV、JSON、dict
  • 解决Edge打开PDF总是没有焦点
  • Homestyler 和 Tripo AI 如何利用人工智能驱动的 3D 建模改变定制室内设计
  • Kubernetes集群架构
  • EasyCVR视频汇聚平台如何配置webrtc播放地址?
  • 车载数据结构 --- ARXML VS JSON
  • 【面试题】技术场景 6、Java 生产环境 bug 排查
  • 代码随想录刷题day05|(数组篇)59.螺旋矩阵 II
  • fastgpt 调用api 调试 写 localhost, 127.0.0.1不行,要 ipconfig 找到本机ip
  • ChatGPT 网络配置问题解决方案
  • Photoshop PS批处理操作教程(批量修改图片尺寸、参数等)
  • winform设置全局异常处理机制来获未处理的异常
  • 语义SEO全解析:如何在搜索引擎中脱颖而出?
  • 《SQL ORDER BY》
  • android分区和root
  • Fluss: First Impression
  • vxlan网络介绍