文章目录

  • 最近面试问了一下单例模式,还要手写几个单例模式做个总结吧
  • 什么是单例模式
  • 单例模式的实现
  • 单例模式的优缺点
  • 单例的实现
  • 饿汉式:一开始就初始化出来,线程安全,没有实现懒加载,可能会造成内存浪费.
  • 懒汉式,线程安全懒汉式,双重锁懒汉式:
  • 静态内部类单例模式(推荐):
  • 枚举类的方式,也可以直接通过Singleton4.INSTANCE使用;


最近面试问了一下单例模式,还要手写几个单例模式做个总结吧

什么是单例模式

单例模式是一种常用的软件设计模式,其定义是单例对象的类只能允许一个实例存在。

单例模式的实现

  1. 将Singleton类的构造方法私有化,不允许通过构造方法创建实例.
  2. 提供静态获取Singleton的方法,返回当前维护的实例.

单例模式的优缺点

优点:

  • 在内存中只有一个对象,节省内存空间;
  • 避免频繁的创建销毁对象,可以提高性能;
  • 避免对共享资源的多重占用,简化访问;
  • 为整个系统提供一个全局访问点。

缺点:

  • 不适用于变化频繁的对象;
  • 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;
  • 如果实例化的对象长时间不被利用,系统会认为该对象是垃圾而被回收,这可能会导致对象状态的丢失;

单例的实现

饿汉式:一开始就初始化出来,线程安全,没有实现懒加载,可能会造成内存浪费.

public class Singleton1 {

  private static Singleton1 singleton = new Singleton1();

  private Singleton1() {
  }

  public static Singleton1 getInstance() {
    return singleton;
  }

}

懒汉式,线程安全懒汉式,双重锁懒汉式:

public class Singleton2 {

  private static Singleton2 singleton ;

  private Singleton2() {
  }

  // 懒汉式,线程不安全
  public static Singleton2 getInstance() {
    if (singleton == null) {
      singleton = new Singleton2();
    }
    return singleton;
  }

  // 懒汉式,线程安全,性能低
  public synchronized static Singleton2 getInstance2() {
    if (singleton == null) {
      singleton = new Singleton2();
    }
    return singleton;
  }

  // 双重加锁机制,线程安全,性能高
  public static Singleton2 getInstance3() {
    if (singleton == null) {
      synchronized (Singleton2.class) {
        if (singleton == null) {
          singleton = new Singleton2();
        }
      }
    }
    return singleton;
  }

}

静态内部类单例模式(推荐):

public class Singleton3 {
  private Singleton3() {
  }

  // 只有第一次调用getInstance方法时,虚拟机才加载 Inner 并初始化instance ,
  // 只有一个线程可以获得对象的初始化锁,其他线程无法进行初始化,保证对象的唯一性。
  public static Singleton3 getInstance() {
    return InnerSingleton.singleton;
  }

  private static class InnerSingleton {
    private static final Singleton3 singleton = new Singleton3();
  }
}

枚举类的方式,也可以直接通过Singleton4.INSTANCE使用;

public enum Singleton4 {
  INSTANCE;
  
  public static Singleton4 getInstance(){
    return INSTANCE;
  }
  
}