单例模式

tech2024-12-04  8

概述

     单例模式:顾名思义,当前类的对象在系统中只有一个,因此节省了资源,也免去频繁创建对象的过程。

使用场景:

1、创建对象成本较高,且需要频繁使用的对象。比如系统中的字典工具类,频繁创建不仅有网络传输成本还有IO成本,频繁创建和销毁对于系统而言开销是比较大的。

2、频繁访问数据库或者文件的对象。

3、系统中的全局计数器

4、多线程应用的线程池工具类

5、Web应用中读取配置的工具类对象

实现方式:

1、常用的饿汉式的实现方式:

        这是我们工作中最常用的一种实现方式,第一编码简单,第二线程安全(由JVM来保证),有以下三个特点:a-私有静态的全局常量 b-私有的构造方法  c-公有的全局访问点

public class Singleton { private static final Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton getInstance() { return INSTANCE; } public static void main(String[] args) { for (int i = 0; i < 100000; i++) { new Thread(() -> System.out.println(Singleton.getInstance())).start(); } } }

2、懒汉式的实现方式:

        这种实现方式编码还是比较复杂的,因为需要主要的细节比较多,这里列举一下:a-私有的静态变量需要用volatile修饰,原因(https://blog.csdn.net/jinyouxinzao/article/details/108245039),否则多线程的场景下会出现半初始化状态的对象; b-需要双重检查,第一重的检查是为了避免锁竞争,第二重检查是为了重复创建对象。

public class LazySingleton { // 注意一定要加上volatile,否则万一遇上了指令重排,会读取到半初始化状态的对象 private static volatile LazySingleton INSTANCE = null; private LazySingleton() {} public static LazySingleton getInstance() { // 这一步的判断是为了避免锁竞争 if (INSTANCE == null) { synchronized(LazySingleton.class) { if (INSTANCE == null) { INSTANCE = new LazySingleton(); } } } return INSTANCE; } public static void main(String[] args) { for (int i = 0; i < 100000; i++) { new Thread(() -> System.out.println(LazySingleton.getInstance())).start(); } } }

3、静态内部类的方式

public class StaSingleton { private StaSingleton() {} private static class Singleton{ static final StaSingleton instance = new StaSingleton(); } public static StaSingleton getInstance() { return Singleton.instance; } public static void main(String[] args) { for (int i = 0; i < 100000; i++) { new Thread(() -> System.out.println(StaSingleton.getInstance())).start(); } } }

4、枚举单例

       这种方式出自神作《effective java》,是一种高逼格的实现方式,让我真正的见识到了大神是怎样写代码的,这种方式有前面几种方式都无法比拟的几个特点:

    4.1 代码空前的简洁

    4.2 可以防止个别杠精通过反射来创建对象

    4.3 可以防止个别杠精通过反序列化的方式操作对象

    以下是枚举单例的代码:

public enum Singleton {          INSTANCE;          public static void main(String[] args) {         for (int i = 0; i < 10000; i++) {             new Thread(()->System.out.println(Singleton.INSTANCE.hashCode())).start();          }     }      }

    

 

 

 

最新回复(0)