单例模式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`实例。

  • 静态内部类在第一次被使用时才会被加载,因此具有懒加载特性,且由于类加载是线程安全的,所以这种方式也是线程安全的。

**优点**:

  • 兼具懒加载和线程安全的优点,是单例模式的一种优雅实现方式。
相关推荐
赵宁灬学长7 小时前
设计模式——单例模式
java·单例模式·设计模式
计算机小混子7 小时前
C++实现设计模式---单例模式 (Singleton)
开发语言·c++·单例模式
只做开心事1 天前
Linux之线程池与单例模式
linux·单例模式
小乖兽技术2 天前
ASP.NET Core 中服务生命周期详解:Scoped、Transient 和 Singleton 的业务场景分析
后端·单例模式·asp.net
目目沐沐2 天前
单例模式
单例模式
HL_LOVE_C3 天前
设计模式-单例模式
单例模式·设计模式
赤水无泪3 天前
创建型模式-单例模式
单例模式
吾当每日三饮五升5 天前
C++单例模式跨DLL调用问题梳理
开发语言·c++·单例模式
臣妾写不来啊5 天前
创建型模式5.单例模式
单例模式