【单例设计模式】揭秘单例模式:从原理到实战的全方位解析(开发者必读)

news2024/9/20 19:32:01

文章目录

  • 深入理解单例设计模式:原理、实现与最佳实践
    • 引言
    • 第一部分:设计模式简介
    • 第二部分:单例模式定义
    • 第三部分:单例模式的优点和缺点
    • 第四部分:单例模式的实现方式
      • 懒汉式
        • 非线程安全的实现
        • 线程安全的实现(双重检查锁定)
      • 饿汉式
        • 静态内部类方式
        • 枚举方式
      • 静态工厂方法
      • 枚举
    • 第五部分:线程安全性
      • 解释多线程环境中的问题
      • 分析不同实现方式下的线程安全问题
        • 懒汉式
        • 饿汉式
      • 提供解决方案和建议
    • 第六部分:单例模式在实际项目中的应用
      • 应用案例 1: 日志记录器
      • 应用案例 2: 数据库连接池
      • 应用案例 3: 配置管理器
    • 第七部分:单例模式的最佳实践
      • 如何避免滥用单例模式
      • 如何处理单例模式与其他设计模式的结合
      • 推荐的使用场景和注意事项
    • 总结

深入理解单例设计模式:原理、实现与最佳实践

引言

在软件开发的过程中,我们经常会遇到需要全局唯一实例的情况。例如,配置管理器、日志记录器或是数据库连接池等,这些组件通常在整个应用程序中只需要一个实例,并且能够被所有组件共享访问。这时,单例设计模式就显得尤为重要。它不仅能够确保系统中某个类只有一个实例存在,还能提供一个全局访问点,从而简化了系统的设计。

为什么重要?

单例设计模式的重要性体现在以下几个方面:

  1. 资源优化:通过单例模式,我们可以确保系统中只有一个实例存在,这对于那些初始化代价较高且频繁使用的对象非常有用,比如数据库连接或文件系统操作。
  2. 全局访问:单例模式提供了一个全局的访问点,使得在任何地方都能轻松获取到同一个实例,这在需要频繁访问同一对象的情况下非常方便。
  3. 易于维护:由于整个系统中只有一个实例存在,因此当需要修改该实例的行为时,只需要在一个地方进行修改即可。

为什么需要了解?

对于软件开发者来说,了解并正确使用单例模式是非常重要的:

  1. 减少冗余:单例模式可以避免重复创建不必要的对象实例,从而减少了内存消耗。
  2. 提高效率:单例模式有助于提高程序的性能,特别是在那些创建成本较高的对象上。
  3. 易于控制:由于单例对象在整个系统中的唯一性,我们可以更容易地控制其生命周期以及行为。
  4. 代码可读性和可维护性:合理使用单例模式可以使代码更加清晰和易于理解。

然而,单例模式也有其局限性和潜在的问题,比如增加了系统的复杂度、可能引起多线程问题等。因此,正确理解和使用单例模式对于软件开发者而言至关重要。

第一部分:设计模式简介

可查这篇文章:【设计模式入门】设计模式全解析:23种经典模式介绍与评级指南(设计师必备)
里面详细讲了23设计模式的简介,可以快速了解设计模式

模式结构
单例模式包含如下角色:

  • Singleton:单例
    在这里插入图片描述
    时序图
    在这里插入图片描述

第二部分:单例模式定义

定义

单例模式是一种常用的软件设计模式,它保证一个类只有一个实例,并提供一个全局访问点来访问该实例。这意味着无论何时何地,只要需要该类的对象,都能得到同一个实例。这种模式通常用于那些需要频繁实例化的类,但又希望保持单一实例的情况下。

单例模式的核心思想和目标

核心思想

  • 保证唯一性:确保类的实例是唯一的。
  • 全局访问:提供一个全局访问点来获取该实例。

目标

  • 资源节约:避免频繁创建和销毁对象所引起的性能开销。
  • 统一管理:方便地管理共享资源或者全局配置等。
  • 简化访问:通过一个全局访问点简化对对象的访问,不需要每次调用时都传递相同的参数。

单例模式适用的场景

  1. 系统配置:对于系统的配置信息,通常只需要加载一次,并在整个应用中保持不变,使用单例模式可以有效地管理这些配置信息。
  2. 日志记录:日志对象在整个应用程序中可能被多个模块使用,单例模式可以确保所有的日志操作都通过同一个日志对象来进行。
  3. 线程池管理:创建线程是一个相对耗时的操作,使用单例模式可以有效地管理线程资源,避免重复创建线程。
  4. 数据库连接:数据库连接是昂贵的资源,单例模式可以确保应用程序中只存在一个数据库连接实例,从而减少资源消耗。
  5. 缓存管理:缓存对象可以用来存储常用数据,以提高系统的响应速度,单例模式可以确保缓存对象的唯一性和一致性。

第三部分:单例模式的优点和缺点

优点

  1. 保证系统内存中该类只存在一个实例
  • 通过限制一个类只能有一个实例,单例模式能够确保系统中不会出现多个相同的对象实例,从而节省内存空间。
  • 这对于那些创建成本高的对象尤其有用,例如数据库连接或大型配置对象。
  1. 允许对唯一实例进行受控访问
  • 单例模式提供了一个全局访问点,使得对单例对象的访问变得简单且可控。
  • 这意味着可以通过单例类的方法来控制对象的行为,例如配置、状态更改等。
  1. 可以节省系统资源
  • 由于单例模式确保了类的实例是唯一的,所以可以避免重复创建和销毁对象带来的资源浪费。
  • 这对于需要频繁访问的资源特别有用,如日志记录器或缓存管理器。

缺点

  1. 增加了系统的复杂度
  • 单例模式的实现通常需要特殊的构造函数和静态方法,这可能会使类的定义变得复杂。
  • 在多线程环境中,还需要考虑线程安全的问题,这会增加额外的复杂性。
  1. 不利于单元测试
  • 单例模式使得在单元测试中模拟单例对象变得困难。
  • 由于单例对象在整个系统中都是唯一的,所以在测试时很难隔离它们的行为,这可能导致测试变得复杂且难以维护。
  1. 可能导致程序变得难以维护
  • 当单例对象被广泛使用时,如果需要修改单例对象的行为,那么这种修改可能会影响到整个系统。
  • 这种全局性的影响使得单例对象成为系统中的一个耦合点,从而降低了系统的可维护性。

小结
虽然单例模式具有明显的优点,但在实际使用中也需要谨慎考虑其潜在的缺点。开发者应该权衡这些优缺点,并根据项目的具体需求来决定是否采用单例模式。在某些情况下,替代的设计模式,如依赖注入,可能更适合。

第四部分:单例模式的实现方式

单例模式可以通过多种方式实现,每种方式都有其特点和适用场景。下面我们将分别介绍几种常见的实现方式。

懒汉式

懒汉式单例模式是在首次使用时才创建实例的模式。这种模式可以分为非线程安全和线程安全两种实现。

非线程安全的实现

这种实现方式简单易懂,但不是线程安全的,也就是说,在多线程环境下可能会出现问题。

public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {}

    public static LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}
线程安全的实现(双重检查锁定)

双重检查锁定(Double-Checked Locking, DCL)是一种优化的线程安全实现方式,它可以避免不必要的同步开销。

public class LazySingletonDCL {
    private volatile static LazySingletonDCL instance;

    private LazySingletonDCL() {}

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

饿汉式

饿汉式单例模式是在类加载时就创建实例的模式。这种方式保证了线程安全性,但可能会造成资源浪费。

静态内部类方式

利用 Java 的静态内部类特性来实现饿汉式的单例模式,这种方式既实现了线程安全,又避免了在类加载时就创建实例。

public class StaticInnerClassSingleton {
    private StaticInnerClassSingleton() {}

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

    public static StaticInnerClassSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
枚举方式

枚举类型本身就是线程安全的,因此可以很自然地用来实现单例模式。

public enum EnumSingleton {
    INSTANCE;

    // 实例变量和方法...
}

静态工厂方法

静态工厂方法是另一种实现单例模式的方式,它使用静态方法来创建和返回实例。

public class StaticFactorySingleton {
    private static StaticFactorySingleton instance;

    private StaticFactorySingleton() {}

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

枚举

枚举类型的单例模式实现简洁且线程安全。

public enum SingletonEnum {
    INSTANCE;

    // 实例变量和方法...
}

小结

以上介绍了几种常见的单例模式实现方式,每种方式都有其特点和适用场景。在选择合适的实现方式时,需要考虑到线程安全性、性能影响以及可维护性等因素。例如,双重检查锁定适合于需要高性能且保证线程安全的场合;而枚举方式则提供了最简洁的线程安全实现。

第五部分:线程安全性

解释多线程环境中的问题

在多线程环境中,单例模式的实现可能会遇到线程安全问题。主要的问题在于,如果没有适当的同步措施,多个线程可能同时尝试创建单例对象的实例,从而违反了单例模式的基本原则——保证一个类只有一个实例。

分析不同实现方式下的线程安全问题

懒汉式
  • 非线程安全的实现
    • 当多个线程同时执行 if (instance == null) 判断时,可能会导致多个线程同时进入条件块并创建新的实例,破坏了单例性质。
    • 例如,两个线程 A 和 B 同时发现 instance 为空,并各自创建了一个新的实例。
public class NonThreadSafeLazySingleton {
    private static NonThreadSafeLazySingleton instance;

    private NonThreadSafeLazySingleton() {}

    public static NonThreadSafeLazySingleton getInstance() {
        if (instance == null) {
            instance = new NonThreadSafeLazySingleton();
        }
        return instance;
    }
}
  • 线程安全的实现(双重检查锁定)
    • 在双重检查锁定中,第一次检查 instance 是否为空,如果为空才进行同步。
    • 这样可以避免在 instance 已经创建后还进行同步,提高了性能。
    • 但是,如果没有正确地使用 volatile 关键字,可能会导致线程安全问题。
    • 如果 new 操作没有完成就返回了引用,其他线程可能会看到未完全构造的实例。
public class ThreadSafeLazySingleton {
    private volatile static ThreadSafeLazySingleton instance;

    private ThreadSafeLazySingleton() {}

    public static ThreadSafeLazySingleton getInstance() {
        if (instance == null) {
            synchronized (ThreadSafeLazySingleton.class) {
                if (instance == null) {
                    instance = new ThreadSafeLazySingleton();
                }
            }
        }
        return instance;
    }
}
饿汉式
  • 静态内部类方式
    • 利用 Java 的类加载机制保证了线程安全性。
    • 当外部类第一次被加载时,静态内部类不会被加载,只有在第一次调用 getInstance() 方法时才会加载内部类并创建实例。
    • 由于类加载机制本身是线程安全的,因此这种方式也是线程安全的。
public class StaticInnerClassSingleton {
    private StaticInnerClassSingleton() {}

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

    public static StaticInnerClassSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
  • 枚举方式
    • 枚举类型的单例实现天生就是线程安全的。
    • 枚举的构造函数会在 JVM 加载时由 JVM 自动保证线程安全地初始化。
    • 因此,这种方式不需要额外的同步措施。
public enum SingletonEnum {
    INSTANCE;

    // 实例变量和方法...
}

提供解决方案和建议

  • 使用 volatile 关键字
    • 在懒汉式实现中使用 volatile 关键字来确保 instance 变量的可见性和禁止指令重排序,从而避免了线程安全问题。
private volatile static ThreadSafeLazySingleton instance;
  • 双重检查锁定

    • 适用于需要在运行时创建实例的懒汉式实现。
    • 确保在多线程环境下也能正确地创建单例对象。
  • 静态内部类方式

    • 推荐用于需要在类加载时创建实例的饿汉式实现。
    • 这种方式不仅线程安全,而且避免了在类加载时就创建实例的性能损失。
  • 枚举方式

    • 最简单的线程安全实现。
    • 适用于不需要额外功能的简单单例实现。

小结
在多线程环境中,单例模式的实现需要特别注意线程安全问题。不同的实现方式有不同的优缺点,选择合适的方式取决于具体的应用场景和性能需求。使用枚举或静态内部类通常是较为推荐的做法,因为它们既简单又高效。

第六部分:单例模式在实际项目中的应用

单例模式在实际项目中有广泛的应用,下面列举了一些典型的使用场景,并分析了为什么在这些场景中选择使用单例模式。

应用案例 1: 日志记录器

案例描述
在大多数应用程序中,日志记录是一项基本的需求。通常,我们需要记录错误、警告以及调试信息等。为了方便管理和统一配置,日志记录器通常被设计为单例。

为什么选择单例模式

  • 统一管理:通过单例模式,可以确保应用程序中只有一个日志记录器实例,这样可以集中控制日志级别、输出格式等配置。
  • 简化访问:单例模式提供的全局访问点使得在程序的任何位置都可以轻松地记录日志信息。
  • 资源节约:由于日志记录器通常需要频繁使用,单例模式可以避免多次创建和销毁实例所带来的资源浪费。

示例代码

public class LoggerSingleton {
    private static LoggerSingleton instance;
    private Logger logger;

    private LoggerSingleton() {
        logger = Logger.getLogger("MyLogger");
    }

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

    public void log(String message) {
        logger.info(message);
    }
}

应用案例 2: 数据库连接池

案例描述
数据库连接是昂贵的资源。为了提高性能,通常使用数据库连接池来管理连接,这样可以复用现有的连接而不是每次都需要新建一个。

为什么选择单例模式

  • 资源管理:连接池需要在整个应用程序中被共享,单例模式可以确保连接池被正确地管理。
  • 效率提升:通过单例模式,可以避免每次查询时都创建新的数据库连接,从而提高了应用程序的整体性能。
  • 统一配置:单例模式使得连接池的配置可以在一个地方进行,便于维护和调整。

示例代码

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.ConcurrentLinkedQueue;

public class DBConnectionPoolSingleton {
    private static DBConnectionPoolSingleton instance;
    private ConcurrentLinkedQueue<Connection> availableConnections;

    private DBConnectionPoolSingleton(int poolSize) {
        availableConnections = new ConcurrentLinkedQueue<>();
        for (int i = 0; i < poolSize; i++) {
            try {
                Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "username", "password");
                availableConnections.add(conn);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public static DBConnectionPoolSingleton getInstance(int poolSize) {
        if (instance == null) {
            synchronized (DBConnectionPoolSingleton.class) {
                if (instance == null) {
                    instance = new DBConnectionPoolSingleton(poolSize);
                }
            }
        }
        return instance;
    }

    public Connection getConnection() {
        return availableConnections.poll();
    }

    public void releaseConnection(Connection conn) {
        if (conn != null) {
            availableConnections.add(conn);
        }
    }
}

应用案例 3: 配置管理器

案例描述
应用程序通常需要读取配置文件中的信息,例如服务器地址、端口号、用户名密码等。为了方便管理这些配置信息,通常会设计一个配置管理器。

为什么选择单例模式

  • 全局访问:配置管理器需要在整个应用程序中被访问,单例模式可以确保配置信息的全局可用性。
  • 减少开销:配置信息通常在应用程序启动时加载一次,之后不再变化。单例模式可以避免重复加载配置文件,从而减少了开销。
  • 简化维护:所有的配置信息都在单例对象中维护,便于维护和更新。

示例代码

import java.util.Properties;

public class ConfigurationManager {
    private static ConfigurationManager instance;
    private Properties properties;

    private ConfigurationManager() {
        properties = new Properties();
        try {
            properties.load(ConfigurationManager.class.getResourceAsStream("/config.properties"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

    public String getProperty(String key) {
        return properties.getProperty(key);
    }
}

小结

通过这些案例,我们可以看到单例模式在实际项目中的应用价值。它不仅能够简化代码结构,还可以提高资源的利用率,同时保证了系统的稳定性和可维护性。在选择使用单例模式时,开发者需要考虑其适用性和潜在的问题,并采取相应的措施来避免这些问题的发生。

当然可以。下面是关于单例模式最佳实践的详细内容:

第七部分:单例模式的最佳实践

单例模式虽然强大,但也容易被误用。下面是一些关于如何合理使用单例模式的最佳实践:

如何避免滥用单例模式

  1. 明确使用场景
  • 确定单例模式是否真的适合当前的场景。考虑是否真的需要一个全局唯一的实例,以及这个实例是否会被频繁地访问。
  • 如果可以使用局部变量或依赖注入等其他方式来代替,应优先考虑这些替代方案。
  1. 避免过度依赖
  • 尽量减少代码对单例对象的直接依赖。过度依赖单例对象会导致代码耦合度过高,难以测试和维护。
  • 考虑使用依赖注入框架来管理对象的生命周期,这可以提高代码的灵活性和可测试性。
  1. 考虑替代方案
  • 对于那些不需要全局唯一实例的场景,可以考虑使用工厂模式或依赖注入等其他设计模式来替代单例模式。

如何处理单例模式与其他设计模式的结合

  1. 与依赖注入结合
  • 即使使用单例模式,也可以通过依赖注入框架(如 Spring、Guice 等)来管理单例对象的生命周期。
  • 这样可以在保证单例特性的基础上,提高代码的可测试性和解耦。
  1. 与工厂模式结合
  • 如果单例对象需要根据不同的情况进行创建,可以考虑使用工厂模式来创建单例对象。
  • 例如,可以根据不同的配置文件或运行环境创建不同的单例实例。

推荐的使用场景和注意事项

  1. 推荐的使用场景
  • 全局配置:例如,配置管理器、日志记录器等需要在整个应用中共享且只需一个实例的组件。
  • 资源管理:例如,数据库连接池、线程池等资源密集型对象。
  • 状态跟踪:例如,全局的状态管理器,用于跟踪整个应用的状态信息。
  1. 注意事项
  • 避免全局状态:尽量减少对全局状态的依赖,因为这可能会导致不可预测的行为。
  • 考虑线程安全性:在多线程环境中使用单例模式时,必须确保其实现是线程安全的。
  • 避免紧耦合:尽量减少代码对单例对象的直接依赖,以降低耦合度。
  • 考虑可测试性
    • 在设计单例模式时,要考虑如何使其易于单元测试。例如,可以考虑使用枚举或静态内部类的方式来实现单例,这些方式通常更容易测试。
    • 如果可能,尽量使用依赖注入来管理单例对象,这样可以在测试时更容易地替换或模拟这些对象。

小结
单例模式是一种强大的工具,但在使用时需要注意其潜在的问题。遵循上述最佳实践可以帮助开发者合理地使用单例模式,避免其潜在的风险,同时提高代码的质量和可维护性。

当然可以。下面是关于结语部分的详细内容:

总结

在这篇文章中,我们深入探讨了单例设计模式的相关知识,包括其定义、核心思想、实现方式以及在实际项目中的应用。我们从以下几个方面进行了详细的讨论:

  1. 设计模式简介:解释了设计模式的基本概念,以及单例模式属于创建型模式。
  2. 单例模式定义:定义了单例模式,并解释了其核心思想和目标。
  3. 单例模式的优点和缺点:分析了单例模式的优势和潜在的缺点。
  4. 单例模式的实现方式:介绍了懒汉式、饿汉式、静态工厂方法等多种实现方式,并重点讨论了线程安全问题。
  5. 线程安全性:分析了不同实现方式下的线程安全问题,并提供了解决方案。
  6. 实际应用:展示了单例模式在实际项目中的几个典型应用案例。
  7. 最佳实践:给出了如何合理使用单例模式的建议,以及如何避免其潜在的问题。

对未来趋势的展望

随着软件开发领域的不断发展和技术的进步,设计模式也在不断进化和发展。未来的趋势可能包括:

  • 更高级别的抽象:随着语言特性和框架的发展,未来的单例模式实现可能会变得更加简洁和高效。
  • 容器化和微服务架构:在容器化和微服务架构中,单例模式的使用方式可能会有所不同,需要考虑服务间的通信和资源管理。
  • 异步编程:随着异步编程的普及,如何在异步环境中正确地使用单例模式也是一个值得研究的方向。

虽然单例模式在很多情况下都非常有用,但它并不是适用于所有场景的灵丹妙药。实际上,设计模式领域非常广阔,还有许多其他模式值得学习和探索,例如工厂模式、策略模式、观察者模式等等。每种模式都有其独特的应用场景和优势,掌握更多的设计模式将有助于您成为一名更优秀的开发者。

鼓励读者在实际工作中积极应用所学的设计模式,并在遇到问题时灵活选择最适合的模式。同时,也建议读者深入研究设计模式背后的原理,以便能够更好地理解和适应不断变化的技术环境。

最后,希望本文能够帮助您更好地理解和使用单例设计模式,并激发您对其他设计模式的兴趣。感谢您的阅读!

本文详细介绍了23种设计模式的基础知识,帮助读者快速掌握设计模式的核心概念,并找到适合实际应用的具体模式:
【设计模式入门】设计模式全解析:23种经典模式介绍与评级指南(设计师必备)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1973447.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vmware ubuntu虚拟机网络联网配置

介绍vmware虚拟机配置基础网络环境&#xff0c;同时连接外网&#xff08;通过桥接模式&#xff09;&#xff0c;以及ubuntu下输入法等基础工具安装。 本文基于ubuntu22.04&#xff0c;前提虚拟机已经完成安装。本文更多是针对vmware虚拟机的设置&#xff0c;之前有一篇针对ubun…

第三关:Git 基础知识

一、Git是什么 Git是一种开源的分布式版本控制系统&#xff0c;广泛应用于软件开发领域&#xff0c;尤其是在协同工作环境中。它为程序员提供了一套必备的工具&#xff0c;使得团队成员能够有效地管理和跟踪代码的历史变更。下面是 Git 的主要功能和作用的规范描述&#xff1a…

Java面试题——第二篇(设计模式)

1. 工厂方法模式 1.1 普通工厂模式 建立一个工厂类&#xff0c;对实现了同一接口的一些类进行实例的创建。 1.2 抽象工厂模式 抽象多个工厂类&#xff0c;提高工厂的可扩展性 定义抽象工厂接口 public interface DeviceFactory { Phone createPhone(); Computer creat…

【工具插件类教学】vHierarchy 2工具编辑器扩展使用

目录 一、下载导入 二、使用介绍 1.便捷小工具 a.图标和颜色Icons and colors b.对象组件缩略图Component minimap c.层级线展示Hierarchy lines d.极简模式Minimal mode e.斑马条纹图案Zebra striping f.激活切换Activation toggle 2、快捷键 一、下载导入 资源官方…

Redis系列之Redis Sentinel

概述 Redis主从集群&#xff0c;一主多从模式&#xff0c;包括一个Master节点和多个Slave节点。Master负责数据的读写&#xff0c;Slave节点负责数据的查询。Master上收到的数据变更&#xff0c;会同步到Slave节点上实现数据的同步。通过这种架构实现可以Redis的读写分离&…

U盘文件或目录损坏无法读取?专业恢复策略全解析

U盘困境&#xff1a;文件目录的隐形危机 在日常的数字生活中&#xff0c;U盘作为便捷的数据存储与传输工具&#xff0c;扮演着至关重要的角色。然而&#xff0c;当U盘中的文件或目录突然遭遇损坏&#xff0c;导致无法被正常读取时&#xff0c;这无疑给用户带来了极大的困扰。这…

达梦数据库的系统视图v$cachers

达梦数据库的系统视图v$cachers 达梦数据库的系统视图V$CACHERS的作用是显示缓存中的项信息&#xff0c;在 ini 参数 USE_PLN_POOL !0 时才统计。这个视图帮助数据库管理员监控和分析缓存的使用情况&#xff0c;优化数据库性能。通过查询V$CACHERS视图&#xff0c;可以获取缓存…

DeferredResult 是如何实现异步处理请求的

最近遇到了一个问题&#xff0c;我们的一个接口需要去轮询另一个第三方接口&#xff0c;导致这个接口占用了太多工作线程&#xff0c;这些工作线程长时间 running&#xff0c;我们需要解决这个问题。 于是&#xff0c;我们的方案是&#xff1a;用 DeferredResult 实现接口异步。…

如何用 ChatGPT 提升学术写作:15 个高效提示

在本文&#xff0c;我们详细探讨了如何利用 ChatGPT 提升学术写作的各个方面。我们帮助学术作者通过生成创意点子、构建论证结构、克服写作障碍以及格式化引用&#xff0c;从而显著提升其学术论文的质量。这 15 条提示不仅可以单独使用&#xff0c;还可作为学习的良好范例。 本…

文件解析漏洞复现

一、IIS 6.X 1.在网站目录创建文件夹名为xxx.asp/xxx.asa 文件夹&#xff0c;里面的任意文件都会被当作asp文件执行 创建1.asp 访问 2.ooo.asp.jpg会被当做asp文件执行 创建一个ooo.asp;.jpg 访问 二、IIS 7.X 上传1.jpg文件在网址后/.php可以成功执行 写一个1.jpg文件内容…

CTFHubret2shellcode-入土为安的第十三天

checksec pwn 没有开保护 并且是64位的 放入IDa64 shiftf12 查看字符串 发现没有shell f5查看主函数 read函数&#xff0c;点进去buf 0x010,0x08. buf的地址 因为我们要把buf填充满 然后再让栈进入shellcode的地址 然后再执行shellcode recvuntil 函数会一直读取数据&#…

Vue3 + JS项目配置ESLint Pretter

前言 如果在开发大型项目 同时为多人协作开发 那么 ESLint 在项目中极为重要 在使用 ESLint 的同时 也需要使用 Pretter插件 统一对代码进行格式化 二者相辅相成 缺一不可 1. 安装 VsCode 插件 在 VsCode 插件市场搜索安装 ESLint 和 Pretter 2. 安装依赖 这里直接在 pac…

SOLIDWORKS教育版支持多种快捷键和自定义工具

在工程设计与教育的广阔领域中&#xff0c;SOLIDWORKS作为一款强大的三维CAD设计软件&#xff0c;凭借其直观的操作界面、丰富的功能集以及对学生及教育机构的特别支持&#xff0c;赢得了广泛的认可与好评。其中&#xff0c;SOLIDWORKS教育版不仅继承了专业版的核心功能&#x…

Android Listview notifyDataSetChanged() 不起作用

private ArrayList<Map<String, String>> data new ArrayList<Map<String, String>>(); private ArrayList<Map<String, String>> delivered_data new ArrayList<Map<String, String>>(); 如果直接将arraylist 的数据直接…

人工智能深度学习系列—深度学习损失函数中的Focal Loss解析

文章目录 1. 背景介绍2. Loss计算公式3. 使用场景4. 代码样例5. 总结 1. 背景介绍 在深度学习的目标检测任务中&#xff0c;类别不平衡问题一直是提升模型性能的拦路虎。Focal Loss损失函数应运而生&#xff0c;专为解决这一难题设计。本文将深入探讨Focal Loss的背景、计算方…

面向对象之设计模式,四种内部类,类关系

面向对象 1. 类关系 继承 使用extends表示,类和类单继承,接口和接口多继承,多个逗号隔开 又叫泛化关系 实现 类和接口是多实现关系,多个逗号隔开,通过关键字 implements表示 依赖 一个类中的局部变量 ,保存了另一个类对象 关联 又叫强依赖,一个类中的成员变量,是另一个类对象…

用Babylon.js 滑动屏幕画图形,签字等

介绍 在上篇文章中我们已经了解到了该游戏引擎的基本搭建过程。比如灯光,摄像头,场景、事件监听等。这里我就不做多介绍。运用以上知识点。我们此时做一个小游戏画图。 效果图 源代码 1.先监听事件是否碰撞到了画板 2.然后判断动作,手指按住屏幕,松开屏幕,滑动屏幕。 …

Linux---进程(4)---进程优先级调度切换

目录 进程优先级 进程切换 前期知识补充 进程切换 进程调度 进程优先级 权限是为了解决能不能享受资源的问题&#xff0c;优先级则是为了解决享受资源的顺序的问题。 进程要访问某种资源&#xff0c;就需要用排队的方式&#xff0c;确定享受资源的先后顺序。因为资源是少…

谷粒商城实战笔记-105~107-全文检索-ElasticSearch-入门

文章目录 一&#xff0c;105-全文检索-ElasticSearch-入门-_cat二&#xff0c;106-全文检索-ElasticSearch-入门-put&post新增数据三&#xff0c;107-全文检索-ElasticSearch-入门-get查询数据&乐观锁字段1&#xff0c;过时的乐观锁-version2&#xff0c;Elasticsearch…

深入源码P3C-PMD:启动源码(2)

下面我们开始从启动探寻 PMD 的源码设计。 pmd 的启动类为 PmdCli&#xff0c;作为命令行的启动器&#xff0c; 其依赖 picocli 作为控制台命令框架。 picocli 官网&#xff1a;https://picocli.info/ Command(name "checksum", mixinStandardHelpOptions true, v…