【Java基础】day15

news2024/12/29 9:45:13

day15

一、为什么需要使用多线程?

1、资源利用率提升,程序处理效率提高
2、软件运行效率提升
3、使用线程可以把占据时间长的程序中的任务放到后台去处理
4、充分利用 CPU 资源,多核 CPU 的情况下会更高效

二、Spring Boot 的启动流程?

1、启动 main() 方法开始
2、初始化配置,通过类加载器 loadFactories 读取 classpath 下所有的 spring.factories 配置文件,创建一些初始配置对象
3、通知监听器启动开始,创建环境对象 environment,用于读取环境配置,如 application.yml 等配置文件。
4、创建应用程序上下文 createApplicationContext,创建 Bean 工厂对象
5、刷新上下文(启动核心步骤)

  • 配置工厂对象,包括上下文类加载器、对象发布处理器、beanFactoryPostProcessor Bean 工厂后置处理器
  • 注册并实例化 Bean 工厂发布处理器,并且调用这些处理器,对包扫描解析(主要是 class 文件)
  • 注册并实例化 Bean 发布处理器 BeanPostProcessor
  • 初始化一些与上下文有特别关系的 Bean 对象,创建 Tomcat 服务器
  • 实例化所有 Bean 工厂缓存的 Bean 对象,将上一步剩下的 Bean 对象全部进行实例化
  • 发布通知,通知上下文刷新完成,启动 Tomcat 服务器

6、通知监听者,启动程序完成

三、ThreadLocal 的底层原理是怎样的?

在线程隔离时,会通过使用线程副本来达到线程之间的隔离。
ThreadLocal 类提供了线程局部变量。这些变量不同于普通变量,因为访问某个变量(通过 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程相关联,比如用户 ID 、事务 ID 这些状态值。

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

ThreadLocal 中的 get 方法,直接利用 Thread 对象获取 ThreadLocalMap 。ThreadLocalMap 中的 Entry 的结构为:

static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}

这里不使用 HashMap 是因为要继承 WeakReference 弱引用,避免内存泄漏。

ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
    table = new Entry[INITIAL_CAPACITY];
    int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
    table[i] = new Entry(firstKey, firstValue);
    size = 1;
    setThreshold(INITIAL_CAPACITY);
}

该 Entry 继承自弱引用,一个对象若只被弱引用所引用,则被认为是不可访问(或弱可访问)的,并因此可能在任何时刻被回收。如果发生弱引用 Entry 被回收(key 被回收,value 没有),这个时候就导致 key 为 null 而 value 存在且为强引用,从而导致有可能访问不到 value 值,又因为 ThreadLocalMap 的生命周期和 Thread 的生命周期相同,所以容易发生内存泄漏。

内存泄漏:程序在申请内存之后,不能去释放一直不被使用的一个内存,导致内存占用最终耗光,可能出现 OOM。

ThreadLocal 的设计中,在进行 set 、get 、remove 、rehash 的操作的时候,会扫描一遍 key 为 null 的一些 entry ;发现之后会将对应的 value 也赋值为 null ,完成一个自动释放的操作。但是需要注意的是,如果 ThreadLocal 以后不会被使用,那么 set、get、remove、rehash 这些方法得不到使用,还是会造成内存的泄漏。

四、String 的 length 方法的返回值

一般来说,在普通的字符串变量下,length 方法返回的是 String 字符串的字面量长度,也就是我们自己人眼可以看到的长度。但是,并不是所有的 String 字符串使用 length 方法都会返回这个长度数值,可以参看下面的代码:

public static void main(String[] args) {
    String b = "𝄞";
    // 音符字符的 UTF-16 编码
    String c = "\uD834\uDD1E";
    System.out.println(c);
    System.out.println(b.length());		// 输出:2
    System.out.println(b.codePointCount(0, b.length()));	// 输出:1
}

这个情况造成的原因,可以在源码中看到答案:
image.png
length() 方法判断长度,基本单位使用的是 Unicode 编码格式来进行判断。Java中 有内码和外码这一区分简单来说

  • 内码: char 或 String 在内存里使用的编码方式。
  • 外码:除了内码都可以认为是“外码”(包括 class 文件的编码)

而在 Java 中,内码 Unicode 使用的是 UTF-16 编码。所以 String 的 length 方法返回的就是字符串在 UTF-16 编码中长度。UTF-16 编码一个字符对于 U+0000-U+FFFF 范围内的字符采用 2 字节进行编码,而对于字符的码点大于 U+FFFF 的字符采用 4 字节进行编码。前者是两字节也就是一个代码单元,后者一个字符是四字节也就是两个代码单元。所以最开始直接调用 length方法返回的是 2 而不是 1。
如果想要按照正常的逻辑,想要返回这个字符的长度,也就是占用多个字符。我们可以使用 codePointCount 方法来实现。看这段代码可以看到具体的方法说明。这个方法返回的就是字符串的目标下标区间的 char 占用长度。
image.png
调用这个方法,就能正常返回 1 了。

五、实现序列化接口为何需要指定序列化 ID?

实现序列化,我们通常需要在类上实现 Serializable 接口。 JDK 官方对于这个接口做出了一些解释:
image.png
这段话的翻译为:

强烈建议所有可序列化的类都显式声明 serialVersionUID 值,因为默认的 serialVersionUID 计算对类的细节高度敏感,这些细节可能因编译器实现而异,因此可能在反序列化期间导致意外的 InvalidClassException 。因此,为了保证在不同的 Java 编译器实现中具有一致的 serialVersionUID,可序列化的类必须声明一个显式的 serialVersionUID 值。还强烈建议显式 serialVersionUID 声明尽可能使用 private 修饰符,因为此类声明仅适用于立即声明的类——serialVersionUID 字段不能用作继承的成员。

如果没有明确指定 serialVersionUID,序列化的时候会根据字段和特定的算法生成一个 serialVersionUID,当属性有变化时这个 id 会发生变化,所以反序列化的时候就会失败,抛出“本地 class 的唯一 id 和流中 class 的唯一 id 不匹配”。
总结:

  • 为了实现跨 Java 编译器的一致性。
  • 默认的 serialVersionUID 计算对类细节高度敏感,这些细节可能因编译器实现而有不同。
  • 为了保证在不同的 java 编译器实现中具有一致的 serialVersionUID 值,需要显式声明 UID 的值。

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

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

相关文章

搭建个人网站没有公网IP地址可以吗?

搭建网站不一定需要公网IP地址&#xff0c;甚至都不需要云服务器或虚拟主机。可以先在本地个人电脑中搭建一个网站&#xff1b;然后网站需要为公网上的其他访客提供访问&#xff1b;所以&#xff0c;需要内网穿透&#xff0c;映射公网域名进行访问。但是完全没必要&#xff0c;…

一文了解Gralde

&#x1f3e0;个人主页&#xff1a;shark-Gao &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是shark-Gao&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f389;目前状况&#xff1a;23届毕业生&#xff0c;目前在某公司实习&#x1f…

python黑马程序员(单例模式工厂模式)笔记

一、单例模式 1、设计模式就是一种编程套路 使用特定的套路得到特定的效果 2、什么时单例设计模式 单例模式就是对一个类&#xff0c;只获取其唯一的类实例对象&#xff0c;持续复用它 节省内存 节省创建对象的开销 非单例模式效果&#xff1a; # 演示单例模式的效果 # 非…

chatgpt相关关键字

听了一堂chatgpt的课程&#xff0c;真假参半&#xff0c;但积累了一些关键词。不知道这些关键字会在什么时候起到作用&#xff0c;先记录下来作为灵感积累 1 自然进化的过程&#xff0c;是人选择工具&#xff0c;也是工具选择人 2 Copliot-自动编程&#xff0c;感觉适用于独立新…

安卓 Windows 通过ts链接获取m3u8视频地址进行视频下载

目录 环境&#xff1a; 解决思路及过程&#xff1a; .TS——> .m3u8 1.利用安卓视频缓存机制合成视频 1.1 找到鲨鱼浏览器目录 1.2 进入Android/data/com.zhijianzhuoyue.sharkbrowser/cashe 缓存目录 1.3 显示隐藏文件 1.4 进入可以看到两个随机生成的视频文件夹&…

傅盛“追风”GPT,猎户星空春天来了?

GPT的横空出世&#xff0c;让冷清已久的商用服务机器人市场&#xff0c;又有了“新故事”。 从技术底层逻辑而言&#xff0c;服务机器人受到这类新技术的影响会更为明显。因为抛开硬件&#xff0c;服务机器人的内核其实就是AI&#xff0c;GPT大模型的出现显然成了现阶段该产业进…

coreldraw2023安装教程及新功能讲解

coreldraw是一款非常好用的设计软件&#xff0c;功能非常强大&#xff0c;它可应用于商标设计、标志制作、模型绘制、插图描画、排版及分色输出等领域&#xff0c;因此受到了不少设计师的青睐&#xff0c; CorelDRAW2023新功能有哪些&#xff1f;CorelDRAW2023最新版本更新怎么…

SpringBoot-核心技术篇

技术掌握导图 六个大标题↓ 配置文件web开发数据访问单元测试指标指控原理解析 配置文件 1.文件类型 1.1、properties 同以前的properties用法 1.2、yaml 1.2.1、简介 YAML是 “YAML Aint Markup Language”&#xff08;YAML不是一种标记语言&#xff09;的递归缩写。在…

JumpServer部署与应用实践

JumpServer部署与介绍 文章目录JumpServer部署与介绍前言堡垒机功能特点主要主件一、在线安装二、环境访问三、堡垒机的应用&#xff08;重点&#xff09;3.1用户与用户组的创建3.2资产管理3.3账号管理3.4权限管理四、应用实践前言 Jumpserver 是一款使用 Python, Django 开发…

Su+ELK实现网络监测(1)——Suricata安装与配置

Suricata安装配置文档一、环境准备1. 基础环境安装2. 安装基础组件二、Luajit部署1. LuaJIT的安装2. 需要更新动态库三、suricata部署1. 安装相关依赖2. 下载、编译并安装suricata3. 执行4. 安装其他组件5. 修改配置文件6. 启动测试7. 安装suricata-update8. 更新规则集9. 启动…

Java多线程:线程组

线程组 可以把线程归属到某一个线程组中&#xff0c;线程组中可以有线程对象&#xff0c;也可以有线程组&#xff0c;组中还可以有线程&#xff0c;这样的组织结构有点类似于树的形式&#xff0c;如图所示&#xff1a; 线程组的作用是&#xff1a;可以批量管理线程或线程组对象…

从4k到42k,软件测试工程师的涨薪史,给我看哭了

清明节一过&#xff0c;盲猜大家已经无心上班&#xff0c;在数着日子准备过五一&#xff0c;但一想到银行卡里的余额……瞬间心情就不美丽了。 最近&#xff0c;2023年高校毕业生就业调查显示&#xff0c;本科毕业月平均起薪为5825元。调查一出&#xff0c;便有很多同学表示自己…

命令行打jar包

命令行打jar包前言jar --helpcvfmMANIFEST.MF压入class文件前言 每一个java开发者运行第一个java项目时都知道项目通常被打成jar包&#xff0c;这些jar包是由IDE工具打的&#xff0c;知其然不知其所以然。 jar --help 用help命令打印jar支持的所有参数&#xff0c;不做过多解…

【GPT开发】人人都能用ChatGPT4.0做Avatar虚拟人直播

0 前言 最近朋友圈以及身边很多朋友都在研究GPT开发&#xff0c;做了各种各样的小工具小Demo&#xff0c;AI工具用起来是真的香&#xff01;在他们的影响下&#xff0c;我也继续捣鼓GPT Demo&#xff0c;希望更多的开发者加入一起多多交流。 上一篇结合即时通 IM SDK捣鼓了一个…

2023mathorcup B题

已完成完整B题C题的模型代码&#xff0c;具体看文末 摘要 城市轨道交通系统作为城市出行的重要组成部分&#xff0c;对于缓解城市交通压力、提高出行效率具有重要意义。优化列车时刻表是提高运营效率、降低企业运营成本、提高乘客满意度的关键。本研究针对城市轨道交通列车时…

SAR ADC系列24:冗余设计

目录 冗余&#xff08;Redundancy&#xff09; 比较器出错&#xff1a;原因 比较器出错&#xff1a;后果 引入冗余&#xff1a;纠错 冗余&#xff1a;容错量 冗余&#xff1a;非二进制CDAC --sub二进制 冗余&#xff1a;提速 另一种冗余设计方法&#xff1a; 下面的关…

tab栏切换

效果&#xff1a; 当鼠标通过上边tab栏时&#xff0c;对应的元素变亮并切换到相应的菜单 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge…

英语学渣如何成功逆袭?聊聊我获得海外工作的真实经历

今天我想和大家分享一下作为一个英语学渣&#xff0c;我是如何成功找到一份海外工作的。希望能够给和我有相似经历的小伙伴们一些启示。以下是兴哥一个女粉丝成功逆袭的经历&#xff0c;大家可以一起旁观一下她的自白。 首先&#xff0c;让我简单介绍一下我的情况。我现在在芬…

【云原生概念和技术】1.2 云原生技术概括(上)

如果想了解或者学习云原生的友友们&#xff0c;欢迎订阅哦&#xff5e;&#x1f917;&#xff0c;目前一周三更&#xff0c;努力码字中&#x1f9d1;‍&#x1f4bb;…目前第一章是一些介绍和概念性的知识&#xff0c;可以先在脑海里有一个知识的轮廓&#xff0c;从第二章开始就…

window eNSP安装使用教程

1&#xff0c;需要的安装包&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1U38OENqOeKXDN0-ipFTxwA?pwdsd12 提取码&#xff1a;sd12 安装eNSP 根据提示&#xff1a;需要先安装wireshark, VirtualBox, winPcap,所以我们接下来先依次安装上面三个安装包。 1&#x…