凌晨突发!核心系统瘫痪,通过Signleton单例模式轻松搞定,但还是被裁员了...

news2024/9/20 10:30:25

在这里插入图片描述

🍅 作者简介:哪吒,CSDN2021博客之星亚军🏆、新星计划导师✌、博客专家💪

🍅 哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师

🍅 技术交流:定期更新Java硬核干货,不定期送书活动

🍅 关注公众号【哪吒编程】,回复 1024 ,获取《10万字208道Java经典面试题总结(附答案)》2024修订版pdf,背题更方便,一文在手,面试我有

目录

    • 一、​简述一下生产场景:
      • 初始化FTP代码样例:
    • 二、Java中一个类中的static对象,在JVM中,会存在多个吗?
    • 三、要保证唯一,是否可以通过Singleton单例模式解决?
      • 先对比一下Singleton和static:
      • 1、相似之处
      • 2、关键区别
      • 3、使用Singleton单例模式改造上述代码
    • 四、具体说一下Singleton是什么?
      • 1、Singleton是指只能被实例化一次的类
      • 2、实现方式
      • 3、Signleton通常用于表示无状态的对象
    • 五、Singleton模式中,static变量需要设置成final吗,为什么?
      • 1、使用final
      • 2、使用final的具体场景
      • 3、不需要final的场景
      • 4、使用final的具体场景,数据库连接池
    • 六、Singleton模式什么场景中需要使用序列化?
      • 1、持久化
      • 2、缓存系统的持久化
      • 3、分布式系统
    • 七、Singleton模式中使用序列化的潜在问题
    • 八、单元素的枚举类型往往是实现singleton的最佳选择?还解决了序列化问题?
      • 1、实现起来非常简单
      • 2、线程安全
      • 3、序列化问题
      • 4、防止反射攻击
      • 5、延迟加载
      • 6、可以实现接口

最近一段时间,一直在解决多线程情况下,通过FTP上传文件,​报错的问题。

一、​简述一下生产场景:

  1. 核心需求:凌晨定时上传文件到FTP服务器
  2. 最开始的代码是单线程实现的,但是速度较慢,需要优化一下。
  3. 根据某字段进行拆分,采用多线程的方式,速度是提升了,但同样也产生了问题(在channelSftp.cd(directory);提示java.io.IOException: Pipe closed
  4. 经过问题的定位分析,结论如下:多线程情况下,其它线程将ftp连接关闭了,导致cd时,channelSftp为无效链接。
  5. 最初的解决方案是:在多线程初始化ftp时,将下面“初始化FTP代码样例:”中的if (sftpConnectionPool == null) {干掉,每次都重新初始化一遍。问题就解决了,上线、搞定,下班,睡觉!

在这里插入图片描述

这里想探讨一个问题:

现场半夜出现故障,客户半夜联系技术人员,技术人员因静音没接到电话,导致现场程序宕机10小时(早上上班才看到并解决),客户投诉,导致技术人员无赔偿被裁,这合理吗?

初始化FTP代码样例:

public static SftpConnectionPool sftpConnectionPool = null;

//初始化
public static boolean init() {
    try{
        //if (sftpConnectionPool == null) {
            String username = "nezha";
            String password = "123456";
            String host = "127.0.0.1";
            int port = 22;
            sftpConnectionPool = new SftpConnectionPool(100, host, port, username, password);
        //}
    }catch(Exception e){
        logger.error("|#初始化SFTP|#异常:" , e);
        return false;
    }

    return true;
}

但,在代码review的时候,技术专家问了我一句,“每次重新初始化static的sftpConnectionPool变量变量,内存中会不会有多个FTP连接池?它们还是一个吗?”

给我干懵逼了!我犹豫了一下,“是的”,但内心是充满不确定的!

作为技术链最顶端的男人,我必须搞清楚这个问题。

二、Java中一个类中的static对象,在JVM中,会存在多个吗?

先说答案,在Java中,一个类中的static对象在JVM中只会存在一个实例。

static表示类级别的成员,而不是实例级别的。

也就是说,static变量或方法是属于整个类的,而不是属于某个特定的实例。

当一个类被加载时,JVM会为该类分配内存,并初始化static变量,这些变量在类的所有实例之间共享,并且在内存中只有一个副本。

不论你创建多少个类的实例,static变量在内存中始终只有一个副本,所有实例共享一个static变量 。

static变量是在类第一次被加载的时候被创建和初始化。即便在多线程环境下,static对象也不会因为线程的并发创建多个实例。

得出结论,上述代码,不管实例化多少次,Java内存中只会有一个FTP连接池。

自信些,伙计,我说的没错。

三、要保证唯一,是否可以通过Singleton单例模式解决?

很多人,开发多年,依旧感觉Signleton和static好像是一样的,比如我。

先对比一下Singleton和static:

1、相似之处

  1. 全局访问点:两者都提供了一种全局访问的方式。
  2. 单一实例:两者都可以确保只有一个实例存在。

2、关键区别

(1)初始化时机

  • singleton:可以实现延迟初始化(懒加载)。
  • static:在类加载时就会初始化。

(2)继承和多态

  • singleton:可以实现继承,支持多态。
  • static:静态成员不能被继承或重写。

(3)接口实现

  • singleton:可以实现接口。
  • static:静态类不能实现接口。

(4)状态管理

  • singleton:可以管理实例状态,更灵活。
  • static:所有的静态成员都共享同一个状态。

(5)序列化

  • singleton:可以实现序列化,但需要特殊处理以维护单例性质。
  • static:静态字段不会被序列化。

(6)资源管理

  • singleton:可以实现生命周期管理,例如在应用程序关闭时释放资源。
  • static:无法确保资源的及时释放。

虽然Singleton和static看起来相似,但Singleton提供了更多的灵活性和控制。它允许延迟初始化、更好的资源管理、更容易的测试和更灵活的设计。然而,这种灵活性是以稍微复杂的实现为代价的。

选择使用static还是Singleton应该基于具体的需求:

  1. 如果只需要一组简单的工具方法,static可能就足够了。
  2. 如果需要更复杂的状态管理、更好的测试性或更灵活的设计,Singleton可能是更好的选择。

3、使用Singleton单例模式改造上述代码

  1. 使用了私有的构造函数,防止外部直接实例化。
  2. 使用volatile关键字修饰instance变量,确保其在多线程环境下的可见性。
  3. 使用双重检查锁定模式来确保线程安全,同时避免了不必要的同步开销。
  4. 将原来的init()方法的逻辑移到了getInstance()方法中,实现了懒加载。
  5. 异常处理方面,我们将异常记录到日志中,然后抛出一个RuntimeException。这样可以确保在初始化失败时,调用者能够及时知道并处理这个问题。
private static volatile SftpConnectionPool instance = null;

private SftpConnectionPoolSingleton() {
    // 私有构造函数,防止直接实例化
}

public static SftpConnectionPool getInstance() {
    if (instance == null) {
        synchronized (SftpConnectionPoolSingleton.class) {
            if (instance == null) {
                try {
                    String username = "nezha";
                    String password = "123456";
                    String host = "127.0.0.1";
                    int port = "22";
                    instance = new SftpConnectionPool(100, host, port, username, password);
                } catch (Exception e) {
                    logger.error("|#初始化SFTP|#异常:", e);
                    throw new RuntimeException("SFTP连接池初始化失败", e);
                }
            }
        }
    }
    return instance;
}

这样,就可以在整个应用程序中使用同一个SftpConnectionPool实例了。

需要注意的是,第一次调用getInstance()时会初始化连接池,可能会花费一些时间,后续的调用将直接返回已创建的实例。

四、具体说一下Singleton是什么?

1、Singleton是指只能被实例化一次的类

Singleton通常指的就是单例模式,确保某个类在整个应用程序生命周期中只能被实例化一次。

无论你在应用程序的任何地方创建多少个这个类的实例,系统始终返回同一个Singleton实例。

通过这种方式,保证了全局的唯一性和一致性。

2、实现方式

实现Singleton的方式有很多种(核心理念都是一样的),这里介绍最常用的一种:

  1. 将类的构造函数设为私有或受保护,防止直接通过new关键字创建实例;
  2. 提供一个公共的静态方法来获取实例。在这个方法或属性内部,判断实例是否已经创建过,如果没有创建则实例化一个,如果已创建则返回现有实例。
public class Singleton {
    private static final Singleton instance = new Singleton();

    private Singleton() {
        // 私有构造函数,防止外部实例化
    }

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

3、Signleton通常用于表示无状态的对象

无状态的对象是指对象的属性值不随时间和使用而改变,或者即使改变了也不会影响应用程序的逻辑。例如,一个工具类会提供一些通用方法,这些方法不依赖于对象的属性值变化。

典型的无状态类可以是一个数据库连接管理器或者一个日志记录器。

Singleton模式的核心在于控制实例的唯一性,而无状态对象因为不需要存储特定状态,所以可以通过Singleton模式方便地实现共享和重用,减少系统的资源开销。

五、Singleton模式中,static变量需要设置成final吗,为什么?

1、使用final

将static变量设置为final,意味着一旦instance被初始化后,就不能再被重新赋值。这样可以确保Singleton实例的不可变性,防止在代码中任何地方意外地修改这个唯一实例。

由于final变量必须在声明时或在构造器中初始化,在类加载时立即创建并初始化final修饰的Singleton实例。

使用final的,通常更简单且线程安全。

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

    private Singleton() {
        // 私有构造函数,防止外部实例化
    }

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

2、使用final的具体场景

(1)配置管理器

当你的应用程序需要一个全局的配置对象,而且这个配置在启动时就确定且不会改变。

INSTANCE 是 final 的,因为配置在应用启动时就加载完毕,不需要改变。

public class ConfigManager {
    private static final ConfigManager INSTANCE = new ConfigManager();
    private final Map<String, String> config;

    private ConfigManager() {
        config = loadConfig(); // 从文件或数据库加载配置
    }

    public static ConfigManager getInstance() {
        return INSTANCE;
    }

    public String getConfig(String key) {
        return config.get(key);
    }

    private Map<String, String> loadConfig() {
        // 实现配置加载逻辑
    }
}

(2)日志管理器

日志管理器通常在应用启动时就初始化,之后不会改变。

public class LogManager {
    private static final LogManager INSTANCE = new LogManager();
    private final Logger logger;

    private LogManager() {
        logger = Logger.getLogger("ApplicationLogger");
    }

    public static LogManager getInstance() {
        return INSTANCE;
    }

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

3、不需要final的场景

如果需要懒加载或在运行时根据条件选择不同的实例时,不需要final。

在这种实现中,你需要确保线程安全性,通常会用同步、双重检查锁定等技术来确保实例的唯一性。

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

4、使用final的具体场景,数据库连接池

在某些情况下,你可能需要根据运行时的条件来初始化连接池,或者需要在运行时更换连接池实现。

instance 不是 final 的,因为我们需要延迟初始化,并可能根据不同的数据库配置创建不同的实例。

public class DatabaseConnectionPool {
    private static DatabaseConnectionPool instance;
    private ConnectionPool pool;

    private DatabaseConnectionPool() {}

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

    public void initializePool(String dbUrl, String username, String password) {
        // 根据传入的参数初始化连接池
        pool = new SomeConnectionPoolImplementation(dbUrl, username, password);
    }

    public Connection getConnection() {
        return pool.getConnection();
    }
}

六、Singleton模式什么场景中需要使用序列化?

1、持久化

你正在开发一个桌面应用程序,需要在应用关闭时保存当前的应用状态,并在下次启动时恢复。

为什么需要序列化:

  • 应用状态需要持久化到磁盘。
  • 在应用重新启动时,需要从磁盘读取并恢复状态。

在下面代码示例中,AppStateManager 不仅可以被序列化,还提供了 saveState 和 loadState 方法来实现状态的保存和加载。

import java.io.*;

public class AppStateManager implements Serializable {
    private static final long serialVersionUID = 1L;
    private static volatile AppStateManager instance;
    private Map<String, Object> stateData;

    private AppStateManager() {
        stateData = new HashMap<>();
    }

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

    public void setState(String key, Object value) {
        stateData.put(key, value);
    }

    public Object getState(String key) {
        return stateData.get(key);
    }

    public void saveState(String filename) throws IOException {
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename))) {
            out.writeObject(this);
        }
    }

    public static void loadState(String filename) throws IOException, ClassNotFoundException {
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename))) {
            instance = (AppStateManager) in.readObject();
        }
    }

    protected Object readResolve() {
        return instance;
    }
}

2、缓存系统的持久化

你正在实现一个缓存系统,该系统需要在服务器重启或计划内维护时将缓存内容持久化,以避免冷启动带来的性能问题。

为什么需要序列化:

  • 缓存内容需要快速地保存到磁盘和从磁盘恢复。
  • 缓存管理器是一个单例,需要在序列化和反序列化过程中保持一致性。
import java.io.*;
import java.util.concurrent.ConcurrentHashMap;

public class CacheManager implements Serializable {
    private static final long serialVersionUID = 1L;
    private static volatile CacheManager instance;
    private ConcurrentHashMap<String, Object> cache;

    private CacheManager() {
        cache = new ConcurrentHashMap<>();
    }

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

    public void put(String key, Object value) {
        cache.put(key, value);
    }

    public Object get(String key) {
        return cache.get(key);
    }

    public void persistCache(String filename) throws IOException {
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename))) {
            out.writeObject(this);
        }
    }

    public static void loadCache(String filename) throws IOException, ClassNotFoundException {
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename))) {
            instance = (CacheManager) in.readObject();
        }
    }

    protected Object readResolve() {
        return instance;
    }
}

3、分布式系统

比如在分布式系统中,有一个配置管理器,它使用Singleton模式来确保配置在整个应用程序中是唯一的。比如数据库连接池。为了提高性能,配置管理器可能会被多个JVM实例共享。

这时候就需要通过网络传输Singleton对象,或者在多个进程之间共享对象状态,这时候需要将Singleton对象序列化为字节流进行传输。

import java.io.Serializable;

public class ConfigManager implements Serializable {
    private static final long serialVersionUID = 1L;
    private static volatile ConfigManager instance;
    private Map<String, String> configData;

    private ConfigManager() {
        configData = new HashMap<>();
    }

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

    public void setConfig(String key, String value) {
        configData.put(key, value);
    }

    public String getConfig(String key) {
        return configData.get(key);
    }

    // 确保反序列化时返回同一个实例
    protected Object readResolve() {
        return getInstance();
    }
}

在这些场景中,序列化单例模式的关键点是:

  1. 实现 Serializable 接口。
  2. 提供一个 readResolve() 方法以确保反序列化时返回单例实例。
  3. 小心处理静态字段,因为它们通常不会被序列化。
  4. 考虑线程安全问题,特别是在反序列化过程中。

使用序列化的单例模式时,需要格外注意保持单例的一致性和线程安全性。同时,也要考虑序列化可能带来的安全风险,确保敏感数据得到适当的保护。

七、Singleton模式中使用序列化的潜在问题

如果直接序列化一个Singleton对象,然后反序列化,反序列化的结果是一个新的对象实例,而不是原来的Singleton实例。这就破坏了Singleton的唯一性。

为了确保在序列化和反序列化过程中不会破坏Singleton模式,通常需要在Singleton类中实现readResolve方法。这个方法会在反序列化过程中被调用,用于确保返回的是当前的Singleton实例,而不是一个新的实例。

import java.io.ObjectStreamException;
import java.io.Serializable;

public class Singleton implements Serializable {
    private static final long serialVersionUID = 1L;

    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {
        // 私有构造函数,防止外部实例化
    }

    public static Singleton getInstance() {
        return INSTANCE;
    }

    // 确保反序列化时返回同一个实例
    private Object readResolve() throws ObjectStreamException {
        return INSTANCE;
    }
}

八、单元素的枚举类型往往是实现singleton的最佳选择?还解决了序列化问题?

1、实现起来非常简单

public enum SingletonEnum {
    INSTANCE;
    
    // 可以添加方法
    public void doSomething() {
        // 实现逻辑
    }
}

通过SingletonEnum.INSTANCE.doSomething();就可以直接用了。

2、线程安全

枚举的实例创建是由JVM在类加载时完成的,天然就是线程安全的。

3、序列化问题

Java确保枚举类型的序列化和反序列化是绝对安全的。JVM会保证反序列化时返回的是同一个实例,不会创建新的实例。

4、防止反射攻击

通过反射创建枚举实例会抛出异常,这进一步保证了单例的唯一性。

5、延迟加载

虽然枚举常量在类加载时就被初始化,但你可以通过内部类来实现延迟加载:

public class SingletonEnum {
    private SingletonEnum() {}
    
    private enum SingletonHolder {
        INSTANCE;
        
        private final SingletonEnum singleton;
        
        SingletonHolder() {
            singleton = new SingletonEnum();
        }
    }
    
    public static SingletonEnum getInstance() {
        return SingletonHolder.INSTANCE.singleton;
    }
}

6、可以实现接口

枚举可以实现接口,这提供了额外的灵活性:

public interface MySingleton {
    void doSomething();
}

public enum SingletonEnum implements MySingleton {
    INSTANCE;
    
    @Override
    public void doSomething() {
        // 实现逻辑
    }
}

👉 GPT功能:

  1. GPT-4o知识问答:支持1000+token上下文记忆功能
  2. 最强代码大模型Code Copilot:代码自动补全、代码优化建议、代码重构等
  3. DALL-E AI绘画:AI绘画 + 剪辑 = 自媒体新时代
  4. 私信哪吒,直接使用GPT-4o

在这里插入图片描述


🏆文章收录于:100天精通Java从入门到就业

哪吒数年工作总结之结晶。

🏆哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师

华为OD机试 2023B卷题库疯狂收录中,刷题点这里

刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。

点击下方名片,回复1024,获取《10万字208道Java经典面试题总结(2024修订版).pdf 》

在这里插入图片描述

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

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

相关文章

selenium底层原理详解

目录 1、selenium版本的演变 1.1、Selenium 1.x&#xff08;Selenium RC时代&#xff09; 1.2、Selenium 2.x&#xff08;WebDriver整合时代&#xff09; 1.3、Selenium 3.x 2、selenium原理说明 3、源码说明 3.1、启动webdriver服务建立连接 3.2、发送操作 1、seleni…

flink车联网项目:维表离线同步(第69天)

系列文章目录 3.3 维表离线同步 3.3.1 思路 3.3.2 示例 3.3.3 其他表开发 3.3.4 部署 3.3.1.1 将表提交到生成环境 3.3.1.2 添加虚拟节点 3.3.1.3 配置计算节点 3.3.1.4 添加虚拟结束节点 3.3.1.5 提交到生产环境 3.3.1.6 发布 3.3.1.7 运维中心 3.3.1.8 补数据 3.3.1.9 补数据…

c++进阶------多态

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

机器学习/数据分析--通俗语言带你入门线性回归(结合案例)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 机器学习是深度学习和数据分析的基础&#xff0c;接下来将更新常见的机器学习算法注意&#xff1a;在打数学建模比赛中&#xff0c;机器学习用的也很多&a…

探索GitLab:从搭建到高效使用的实用指南

企业里为什么喜欢使用GitLab 一、GitLab简介二、搭建GitLab三、GitLab的权限管理3.1、用户注册3.2、创建用户组3.3、为用户组添加用户3.4、为工程添加访问权限 四、GitLab的code review五、团队知识管理六、总结 一、GitLab简介 GitLab是利用 Ruby on Rails 一个开源的版本管理…

Adobe Media Encoder ME 2023-23.6.6.2 解锁版下载安装教程 (专业的视频和音频编码渲染工具)

前言 Adobe Media Encoder&#xff08;简称Me&#xff09;是一款专业的音视频格式转码软件&#xff0c;文件格式转换软件。主要用来对音频和视频文件进行编码转换&#xff0c;支持格式非常多&#xff0c;使用系统预设设置&#xff0c;能更好的导出与相关设备兼容的文件。 一、…

网站怎么做敏感词过滤,敏感词过滤的思路和实践

敏感词过滤是一种在网站、应用程序或平台中实现内容审查的技术&#xff0c;用于阻止用户发布包含不适当、非法或不符合政策的内容。我们在实际的网站运营过程中&#xff0c;往往需要担心某些用户发布的内容中包含敏感词汇&#xff0c;这些词汇往往会导致我们的网站被用户举报&a…

JVM的组成

JVM 运行在操作系统之上 java二进制字节码文件的运行环境 JVM的组成部分 java代码在编写完成后编译成字节码文件通过类加载器 来到运行数据区,主要作用是加载字节码到内存 包含 方法区/元空间 堆 程序计数器,虚拟机栈,本地方法栈等等 随后来到执行引擎,主要作用是翻译字…

系统工程与信息系统(上)

系统工程 概念 【系统工程】是一种组织管理技术。 【系统工程】是为了最好的实现系统的目的&#xff0c;对系统的组成要素、组织结构、信息流、控制机构进行分析研究的科学方法。 【系统工程】从整体出发、从系统观念出发&#xff0c;以求【整体最优】 【系统工程】利用计算机…

信息搜集--敏感文件Banner

免责声明:本文仅做分享参考... git安装: Windows10下安装Git_win10安装git好慢-CSDN博客 git目录结构: Git 仓库目录 .git 详解-CSDN博客 敏感目录泄露 1-git泄露 Git是一个开源的分布式版本控制系统,我们简单的理解为Git 是一个*内容寻址文件系统*&#xff0c;也就是说Gi…

二十四、解释器模式

文章目录 1 基本介绍2 案例2.1 Instruction 接口2.2 StartInstruction 类2.3 PrimitiveInstruction 类2.4 RepeatInstruction 类2.5 InstructionList 类2.6 Context 类2.7 Client 类2.8 Client 类的运行结果2.9 总结 3 各角色之间的关系3.1 角色3.1.1 AbstractExpression ( 抽象…

Nexpose漏扫

免责声明:本文仅做分享参考... nexpose官网: Nexpose On-Premise Vulnerability Scanner - Rapid7 Rapid7的Nexpose是一款非常专业的漏洞扫描软件。有community版本和enterprise版本。 其中community版是免费的&#xff0c;但是功能简单&#xff1b;enterprise版本功能强大.…

适用于 Windows 10 的最佳免费数据恢复软件是什么?

有没有适用于 Windows 10 的真正免费的数据恢复软件&#xff1f; 丢失重要数据&#xff0c;无论是由于硬件问题、软件问题、意外删除、格式化还是病毒和恶意软件&#xff0c;确实很麻烦。当你面临数据丢失时&#xff0c;你可能真心希望找到一款免费的数据恢复软件&#xff0c;…

【C++指南】深入剖析:C++中的引用

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《C指南》 期待您的关注 目录 引言&#xff1a; 一、引用的基本概念 1. 定义与特性 2. 语法与声明 二、引用的进阶用法 1. 函…

Python高手参考手册:迭代器协议详解

在Python中&#xff0c;迭代器协议提供了一种灵活的方式来遍历容器中的元素。本文将详细介绍迭代器协议的基础知识、其实现机制以及一些实用的应用案例。 迭代器协议概述 1.1 迭代器与迭代协议 迭代器协议定义了如何遍历容器中的元素。在Python中&#xff0c;任何实现了迭代…

Android:使用Gson常见问题(包含解决将Long型转化为科学计数法的问题)

一、解决将Long型转化为科学计数法的问题 1.1 场景 将一个对象转为Map类型时&#xff0c;调用Gson.fromJson发现&#xff0c;原来对象中的long类型的personId字段&#xff0c;被解析成了科学计数法&#xff0c;导致请求接口失败&#xff0c;报参数错误。 解决结果图 1.2、Exa…

轻松掌握域名系统(DNS):基础小白的入门指南

文章目录 域名系统概述DNS 的发展和结构DNS 的服务和功能互联网的域名结构域名服务器的类型和功能域名解析的过程DNS资源记录小结 域名系统概述 域名系统&#xff08;Domain Name System&#xff0c;DNS&#xff09; 是一种核心服务&#xff0c;它使得网络应用能够在应用层使用…

腾讯地图SDK Android版开发 6 显示覆盖物

腾讯地图SDK Android版开发 6 显示覆盖物 前言地图类中覆盖物的接口覆盖物类Marker示例Polyline示例Polygon示例Arc示例Circle示例移除示例效果图 Marker的更多属性常用属性交互碰撞动画其它属性 折线的更多属性常用属性交互其它属性 多边形的更多属性常用属性交互其它属性 Arc…

【手抖拜拜!特发性震颤患者的专属锻炼秘籍,轻松改善生活品质】

Hey小伙伴们~&#x1f44b; 今天咱们来聊聊一个可能不那么常被提及&#xff0c;但却实实在在影响着很多人生活质量的话题——特发性震颤。如果你或你身边的人正为此困扰&#xff0c;别怕&#xff0c;这篇笔记就是你们的“稳手宝典”&#x1f4da;&#xff01; &#x1f308; 了…

【论文复现】 | 改善抑郁估计从面部对齐,训练优化和调度

文章目录 1、Introduction2、Related work3、 Proposed methodology3.1. Preprocessing and face alignment3.2 Architecture3.3 Data Augmentation3.4 Training 4、Experimental analysis and results4.1 Datasets4.2 Experimental setup4.3 Protocol and Performance metrice…