Skip to content

Commit e52e698

Browse files
committed
update: 部分内容完善和格式修正
1 parent ad57ac4 commit e52e698

14 files changed

+36
-20
lines changed

docs/cs-basics/network/other-network-questions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ SSE (Server-Sent Events) 和 WebSocket 都是用来实现服务器向浏览器
450450

451451
![](https://oss.javaguide.cn/github/javaguide/cs-basics/network/deepseek-sse-eventstream.png)
452452

453-
可以看到,响应头应里包含了 `text/event-stream`说明使用的确实是SSE。并且,响应数据也确实是持续分块传输。
453+
可以看到,响应头应里包含了 `text/event-stream`说明使用的确实是 SSE。并且,响应数据也确实是持续分块传输。
454454

455455
## PING
456456

docs/cs-basics/network/other-network-questions2.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@ tag:
5757
- **文件传输 (FTP, SCP):** 文件内容不允许有任何字节丢失或错序。
5858
- **邮件收发 (SMTP, POP3, IMAP):** 邮件内容需要完整无误地送达。
5959
- **远程登录 (SSH, Telnet):** 命令和响应需要准确传输。
60-
- ......
60+
- ……
6161

6262
**实时性、速度和效率优先,并且应用能容忍少量数据丢失或乱序**时,通常选择 UDP。UDP 开销小、传输快,没有建立连接和保证可靠性的复杂过程。典型应用场景如下:
6363

6464
- **实时音视频通信 (VoIP, 视频会议, 直播):** 偶尔丢失一两个数据包(可能导致画面或声音短暂卡顿)通常比因为等待重传(TCP 机制)导致长时间延迟更可接受。应用层可能会有自己的补偿机制。
6565
- **在线游戏:** 需要快速传输玩家位置、状态等信息,对实时性要求极高,旧的数据很快就没用了,丢失少量数据影响通常不大。
6666
- **DHCP (动态主机配置协议):** 客户端在请求 IP 时自身没有 IP 地址,无法满足 TCP 建立连接的前提条件,并且 DHCP 有广播需求、交互模式简单以及自带可靠性机制。
6767
- **物联网 (IoT) 数据上报:** 某些场景下,传感器定期上报数据,丢失个别数据点可能不影响整体趋势分析。
68-
- ......
68+
- ……
6969

7070
### HTTP 基于 TCP 还是 UDP?
7171

docs/database/mysql/mysql-index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ tag:
2424
**索引的优点:**
2525

2626
1. **查询速度起飞 (主要目的)**:通过索引,数据库可以**大幅减少需要扫描的数据量**,直接定位到符合条件的记录,从而显著加快数据检索速度,减少磁盘 I/O 次数。
27-
2. **保证数据唯一性**:通过创建**唯一索引 (Unique Index)**,可以确保表中的某一列(或几列组合)的值是独一无二的,比如用户ID、邮箱等。主键本身就是一种唯一索引。
27+
2. **保证数据唯一性**:通过创建**唯一索引 (Unique Index)**,可以确保表中的某一列(或几列组合)的值是独一无二的,比如用户 ID、邮箱等。主键本身就是一种唯一索引。
2828
3. **加速排序和分组**:如果查询中的 ORDER BY 或 GROUP BY 子句涉及的列建有索引,数据库往往可以直接利用索引已经排好序的特性,避免额外的排序操作,从而提升性能。
2929

3030
**索引的缺点:**
3131

32-
1. **创建和维护耗时**:创建索引本身需要时间,特别是对大表操作时。更重要的是,当对表中的数据进行**增、删、改 (DML操作)** 时,不仅要操作数据本身,相关的索引也必须动态更新和维护,这会**降低这些 DML 操作的执行效率**
32+
1. **创建和维护耗时**:创建索引本身需要时间,特别是对大表操作时。更重要的是,当对表中的数据进行**增、删、改 (DML 操作)** 时,不仅要操作数据本身,相关的索引也必须动态更新和维护,这会**降低这些 DML 操作的执行效率**
3333
2. **占用存储空间**:索引本质上也是一种数据结构,需要以物理文件(或内存结构)的形式存储,因此会**额外占用一定的磁盘空间**。索引越多、越大,占用的空间也就越多。
3434
3. **可能被误用或失效**:如果索引设计不当,或者查询语句写得不好,数据库优化器可能不会选择使用索引(或者选错索引),反而导致性能下降。
3535

@@ -38,7 +38,7 @@ tag:
3838
**不一定。** 大多数情况下,合理使用索引确实比全表扫描快得多。但也有例外:
3939

4040
- **数据量太小**:如果表里的数据非常少(比如就几百条),全表扫描可能比通过索引查找更快,因为走索引本身也有开销。
41-
- **查询结果集占比过大**:如果要查询的数据占了整张表的大部分(比如超过20%-30%),优化器可能会认为全表扫描更划算,因为通过索引多次回表(随机I/O)的成本可能高于一次顺序的全表扫描。
41+
- **查询结果集占比过大**:如果要查询的数据占了整张表的大部分(比如超过 20%-30%),优化器可能会认为全表扫描更划算,因为通过索引多次回表(随机 I/O)的成本可能高于一次顺序的全表扫描。
4242
- **索引维护不当或统计信息过时**:导致优化器做出错误判断。
4343

4444
## 索引底层数据结构选型

docs/database/sql/sql-questions-05.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ HAVING
5353
(COUNT(*) - COUNT(submit_time)) > 0;
5454
```
5555

56-
利用 `COUNT(*) `统计分组内的总记录数,`COUNT(submit_time)` 只统计 `submit_time` 字段不为 NULL 的记录数(即已完成数)。两者相减,就是未完成数。
56+
利用 `COUNT(*)`统计分组内的总记录数,`COUNT(submit_time)` 只统计 `submit_time` 字段不为 NULL 的记录数(即已完成数)。两者相减,就是未完成数。
5757

5858
写法 2:
5959

docs/java/collection/java-collection-precautions-for-use.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ public static <T> T requireNonNull(T obj) {
134134
return obj;
135135
}
136136
```
137-
> `Collectors`也提供了无需mergeFunction的`toMap()`方法,但此时若出现key冲突,则会抛出`duplicateKeyException`异常,因此强烈建议使用`toMap()`方法必填mergeFunction。
137+
138+
> `Collectors`也提供了无需 mergeFunction 的`toMap()`方法,但此时若出现 key 冲突,则会抛出`duplicateKeyException`异常,因此强烈建议使用`toMap()`方法必填 mergeFunction。
138139
139140
## 集合遍历
140141

docs/java/collection/java-collection-questions-02.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,10 @@ JDK1.7 及之前版本的 `HashMap` 在多线程环境下扩容操作可能存
359359

360360
### ⭐️HashMap 为什么线程不安全?
361361

362-
JDK1.7 及之前版本,在多线程环境下,`HashMap` 扩容时会造成死循环和数据丢失的问题。
362+
`HashMap` 不是线程安全的。在多线程环境下对 `HashMap` 进行并发写操作,可能会导致两种主要问题:
363+
364+
1. **数据丢失**:并发 `put` 操作可能导致一个线程的写入被另一个线程覆盖。
365+
2. **无限循环**:在 JDK 7 及以前的版本中,并发扩容时,由于头插法可能导致链表形成环,从而在 `get` 操作时引发无限循环,CPU 飙升至 100%。
363366

364367
数据丢失这个在 JDK1.7 和 JDK 1.8 中都存在,这里以 JDK 1.8 为例进行介绍。
365368

docs/java/concurrent/java-concurrent-questions-02.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ public class SynchronizedDemo {
664664

665665
`synchronized` 是依赖于 JVM 实现的,前面我们也讲到了 虚拟机团队在 JDK1.6 为 `synchronized` 关键字进行了很多优化,但是这些优化都是在虚拟机层面实现的,并没有直接暴露给我们。
666666

667-
`ReentrantLock` 是 JDK 层面实现的(也就是 API 层面,需要 lock() 和 unlock() 方法配合 try/finally 语句块来完成),所以我们可以通过查看它的源代码,来看它是如何实现的。
667+
`ReentrantLock` 是 JDK 层面实现的(也就是 API 层面,需要 `lock()``unlock()` 方法配合 `try/finally` 语句块来完成),所以我们可以通过查看它的源代码,来看它是如何实现的。
668668

669669
#### ReentrantLock 比 synchronized 增加了一些高级功能
670670

docs/java/concurrent/java-concurrent-questions-03.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ new RejectedExecutionHandler() {
628628

629629
- 容量为 `Integer.MAX_VALUE``LinkedBlockingQueue`(有界阻塞队列):`FixedThreadPool``SingleThreadExecutor``FixedThreadPool`最多只能创建核心线程数的线程(核心线程数和最大线程数相等),`SingleThreadExecutor`只能创建一个线程(核心线程数和最大线程数都是 1),二者的任务队列永远不会被放满。
630630
- `SynchronousQueue`(同步队列):`CachedThreadPool``SynchronousQueue` 没有容量,不存储元素,目的是保证对于提交的任务,如果有空闲线程,则使用空闲线程来处理;否则新建一个线程来处理任务。也就是说,`CachedThreadPool` 的最大线程数是 `Integer.MAX_VALUE` ,可以理解为线程数是可以无限扩展的,可能会创建大量线程,从而导致 OOM。
631-
- `DelayedWorkQueue`(延迟队列):`ScheduledThreadPool``SingleThreadScheduledExecutor``DelayedWorkQueue` 的内部元素并不是按照放入的时间排序,而是会按照延迟的时间长短对任务进行排序,内部采用的是“堆”的数据结构,可以保证每次出队的任务都是当前队列中执行时间最靠前的。`DelayedWorkQueue` 添加元素满了之后会自动扩容,增加原来容量的 50%,即永远不会阻塞,最大扩容可达 `Integer.MAX_VALUE`,所以最多只能创建核心线程数的线程
631+
- `DelayedWorkQueue`(延迟队列):`ScheduledThreadPool``SingleThreadScheduledExecutor``DelayedWorkQueue` 的内部元素并不是按照放入的时间排序,而是会按照延迟的时间长短对任务进行排序,内部采用的是“堆”的数据结构,可以保证每次出队的任务都是当前队列中执行时间最靠前的。`DelayedWorkQueue` 是一个无界队列。其底层虽然是数组,但当数组容量不足时,它会自动进行扩容,因此队列永远不会被填满。当任务不断提交时,它们会全部被添加到队列中。这意味着线程池的线程数量永远不会超过其核心线程数,最大线程数参数对于使用该队列的线程池来说是无效的
632632
- `ArrayBlockingQueue`(有界阻塞队列):底层由数组实现,容量一旦创建,就不能修改。
633633

634634
### ⭐️线程池处理任务的流程了解吗?

docs/java/jvm/memory-area.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ Java 虚拟机规范对于运行时数据区域的规定是相当宽松的。以
8080

8181
**操作数栈** 主要作为方法调用的中转站使用,用于存放方法执行过程中产生的中间计算结果。另外,计算过程中产生的临时变量也会放在操作数栈中。
8282

83-
**动态链接** 主要服务一个方法需要调用其他方法的场景。Class 文件的常量池里保存有大量的符号引用比如方法引用的符号引用。当一个方法要调用其他方法,需要将常量池中指向方法的符号引用转化为其在内存地址中的直接引用。动态链接的作用就是为了将符号引用转换为调用方法的直接引用,这个过程也被称为 **动态连接**
83+
**动态链接**是 Java 虚拟机实现方法调用的关键机制之一。在 Class 文件中,方法调用以**符号引用**的形式存在于常量池。为了执行调用,这些符号引用必须被转换为内存中的**直接引用**。这个转换过程分为两种情况:对于静态方法、私有方法等在编译期就能确定版本的方法,这个转换在**类加载的解析阶段**就完成了,这称为**静态解析**。而对于需要根据对象实际类型才能确定具体实现的**虚方法**(这是实现多态的基础),这个转换过程则被推迟到**程序运行期间**,由**动态链接**来完成。因此,**动态链接**的核心作用是**在运行时解析虚方法的调用点,将其链接到正确的方法版本上**
8484

8585
![](https://oss.javaguide.cn/github/javaguide/jvmimage-20220331175738692.png)
8686

@@ -177,7 +177,19 @@ MaxTenuringThreshold of 20 is invalid; must be between 0 and 15
177177
178178
《Java 虚拟机规范》只是规定了有方法区这么个概念和它的作用,方法区到底要如何实现那就是虚拟机自己要考虑的事情了。也就是说,在不同的虚拟机实现上,方法区的实现是不同的。
179179
180-
当虚拟机要使用一个类时,它需要读取并解析 Class 文件获取相关信息,再将信息存入到方法区。方法区会存储已被虚拟机加载的 **类信息、字段信息、方法信息、常量、静态变量、即时编译器编译后的代码缓存等数据**。
180+
当虚拟机加载一个类时,它会从 Class 文件中解析出相应的信息,并将这些**元数据**存入方法区。具体来说,方法区主要存储以下核心数据:
181+
182+
1. **类的元数据**:包括类的完整结构,如类名、父类、实现的接口、访问修饰符,以及字段和方法的详细信息(名称、类型、修饰符等)。
183+
2. **方法的字节码**:每个方法的原始指令序列。
184+
3. **运行时常量池**:每个类独有的,由 Class 文件中的常量池转换而来,用于存放编译期生成的各种字面量和对类型、字段、方法的符号引用。
185+
186+
需要特别注意的是,以下几类数据虽然在逻辑上与类相关,但在 HotSpot 虚拟机中,它们并不存储在方法区内:
187+
188+
- **静态变量(Static Variables)**:自 JDK 7 起,静态变量已从方法区(永久代)**移至 Java 堆(Heap)中**,与该类的 `java.lang.Class` 对象一起存放。
189+
- **字符串常量池(String Pool)**:同样自 JDK 7 起,字符串常量池也**移至 Java 堆中**。
190+
- **即时编译器编译后的代码缓存(JIT Code Cache)**:JIT 编译器将热点方法的字节码编译成的本地机器码,存放在一个**独立的、名为“Code Cache”的内存区域**,而不是方法区本身。这样做是为了实现更高效的执行和内存管理。
191+
192+
![method-area-jdk1.7](https://oss.javaguide.cn/github/javaguide/java/jvm/method-area-jdk1.7.png)
181193
182194
**方法区和永久代以及元空间是什么关系呢?** 方法区和永久代以及元空间的关系很像 Java 中接口和类的关系,类实现了接口,这里的类就可以看作是永久代和元空间,接口可以看作是方法区,也就是说永久代以及元空间是 HotSpot 虚拟机对虚拟机规范中方法区的两种实现方式。并且,永久代是 JDK 1.8 之前的方法区实现,JDK 1.8 及以后方法区的实现变成了元空间。
183195

docs/java/new-features/java22-23.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ JDK 23 一共有 12 个新特性:
2525
- [JEP 476:模块导入声明 (预览)](https://openjdk.org/jeps/476)
2626
- [JEP 477:未命名类和实例 main 方法 (第三次预览)](https://openjdk.org/jeps/477)
2727
- [JEP 480:结构化并发 (第三次预览)](https://openjdk.org/jeps/480)
28-
- [JEP 481: 作用域值 (第三次预览)](https://openjdk.org/jeps/481)
28+
- [JEP 481:作用域值 (第三次预览)](https://openjdk.org/jeps/481)
2929
- [JEP 482:灵活的构造函数体(第二次预览)](https://openjdk.org/jeps/482)
3030

3131
JDK 22 的新特性如下:

0 commit comments

Comments
 (0)