Skip to content

Commit 7cf404b

Browse files
committed
[docs update]内容修正
1 parent 74fc413 commit 7cf404b

File tree

5 files changed

+63
-12
lines changed

5 files changed

+63
-12
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ HTTP/2.0 多路复用效果图(图源: [HTTP/2 For Web Developers](https://b
215215
- **队头阻塞**:HTTP/2.0 多请求复用一个 TCP 连接,一旦发生丢包,就会阻塞住所有的 HTTP 请求。由于 QUIC 协议的特性,HTTP/3.0 在一定程度上解决了队头阻塞(Head-of-Line blocking, 简写:HOL blocking)问题,一个连接建立多个不同的数据流,这些数据流之间独立互不影响,某个数据流发生丢包了,其数据流不受影响(本质上是多路复用+轮询)。
216216
- **连接迁移**:HTTP/3.0 支持连接迁移,因为 QUIC 使用 64 位 ID 标识连接,只要 ID 不变就不会中断,网络环境改变时(如从 Wi-Fi 切换到移动数据)也能保持连接。而 TCP 连接是由(源 IP,源端口,目的 IP,目的端口)组成,这个四元组中一旦有一项值发生改变,这个连接也就不能用了。
217217
- **错误恢复**:HTTP/3.0 具有更好的错误恢复机制,当出现丢包、延迟等网络问题时,可以更快地进行恢复和重传。而 HTTP/2.0 则需要依赖于 TCP 的错误恢复机制。
218-
- **安全性**:在 HTTP/2.0 中,TLS 用于加密和认证整个 HTTP 会话,包括所有的 HTTP 头部和数据负载。TLS的工作是在 TCP 层之上,它加密的是在 TCP 连接中传输的应用层的数据,并不会对 TCP 头部以及 TLS 记录层头部进行加密,所以在传输的过程中 TCP 头部可能会被攻击者篡改来干扰通信。而 HTTP/3.0 的 QUIC 对整个数据包(包括报文头和报文体)进行了加密与认证处理,保障安全性。
218+
- **安全性**:在 HTTP/2.0 中,TLS 用于加密和认证整个 HTTP 会话,包括所有的 HTTP 头部和数据负载。TLS 的工作是在 TCP 层之上,它加密的是在 TCP 连接中传输的应用层的数据,并不会对 TCP 头部以及 TLS 记录层头部进行加密,所以在传输的过程中 TCP 头部可能会被攻击者篡改来干扰通信。而 HTTP/3.0 的 QUIC 对整个数据包(包括报文头和报文体)进行了加密与认证处理,保障安全性。
219219

220220
HTTP/1.0、HTTP/2.0 和 HTTP/3.0 的协议栈比较:
221221

docs/database/redis/redis-questions-01.md

+8-3
Original file line numberDiff line numberDiff line change
@@ -780,10 +780,15 @@ dynamic-hz yes
780780

781781
### 大量 key 集中过期怎么办?
782782

783-
如果存在大量 key 集中过期的问题,可能会使 Redis 的请求延迟变高。可以采用下面的可选方案来应对
783+
当 Redis 中存在大量 key 在同一时间点集中过期时,可能会导致以下问题
784784

785-
1. 尽量避免 key 集中过期,在设置键的过期时间时尽量随机一点。
786-
2. 对过期的 key 开启 lazyfree 机制(修改 `redis.conf` 中的 `lazyfree-lazy-expire`参数即可),这样会在后台异步删除过期的 key,不会阻塞主线程的运行。
785+
- **请求延迟增加:** Redis 在处理过期 key 时需要消耗 CPU 资源,如果过期 key 数量庞大,会导致 Redis 实例的 CPU 占用率升高,进而影响其他请求的处理速度,造成延迟增加。
786+
- **内存占用过高:** 过期的 key 虽然已经失效,但在 Redis 真正删除它们之前,仍然会占用内存空间。如果过期 key 没有及时清理,可能会导致内存占用过高,甚至引发内存溢出。
787+
788+
为了避免这些问题,可以采取以下方案:
789+
790+
1. **尽量避免 key 集中过期**: 在设置键的过期时间时尽量随机一点。
791+
2. **开启 lazy free 机制**: 修改 `redis.conf` 配置文件,将 `lazyfree-lazy-expire` 参数设置为 `yes`,即可开启 lazy free 机制。开启 lazy free 机制后,Redis 会在后台异步删除过期的 key,不会阻塞主线程的运行,从而降低对 Redis 性能的影响。
787792

788793
### Redis 内存淘汰策略了解么?
789794

docs/java/basis/java-basic-questions-02.md

+43-5
Original file line numberDiff line numberDiff line change
@@ -706,9 +706,14 @@ System.out.println(aa==bb); // true
706706
707707
### String s1 = new String("abc");这句话创建了几个字符串对象?
708708
709-
会创建 12 个字符串对象。
709+
先说答案:会创建 12 个字符串对象。
710710
711-
1、如果字符串常量池中不存在字符串对象 “abc”,那么它首先会在字符串常量池中创建字符串对象 "abc",然后在堆内存中再创建其中一个字符串对象 "abc"
711+
1. 字符串常量池中不存在 "abc":会创建 2 个 字符串对象。一个在字符串常量池中,由 `ldc` 指令触发创建。一个在堆中,由 `new String()` 创建,并使用常量池中的 "abc" 进行初始化。
712+
2. 字符串常量池中已存在 "abc":会创建 1 个 字符串对象。该对象在堆中,由 `new String()` 创建,并使用常量池中的 "abc" 进行初始化。
713+
714+
下面开始详细分析。
715+
716+
1、如果字符串常量池中不存在字符串对象 “abc”,那么它首先会在字符串常量池中创建字符串对象 "abc",然后在堆内存中再创建其中一个字符串对象 "abc"
712717
713718
示例代码(JDK 1.8):
714719
@@ -718,9 +723,33 @@ String s1 = new String("abc");
718723
719724
对应的字节码:
720725
721-
![](https://oss.javaguide.cn/github/javaguide/open-source-project/image-20220413175809959.png)
726+
```java
727+
// 在堆内存中分配一个尚未初始化的 String 对象。
728+
// #2 是常量池中的一个符号引用,指向 java/lang/String 类。
729+
// 在类加载的解析阶段,这个符号引用会被解析成直接引用,即指向实际的 java/lang/String 类。
730+
0 new #2 <java/lang/String>
731+
// 复制栈顶的 String 对象引用,为后续的构造函数调用做准备。
732+
// 此时操作数栈中有两个相同的对象引用:一个用于传递给构造函数,另一个用于保持对新对象的引用,后续将其存储到局部变量表。
733+
3 dup
734+
// JVM 先检查字符串常量池中是否存在 "abc"。
735+
// 如果常量池中已存在 "abc",则直接返回该字符串的引用;
736+
// 如果常量池中不存在 "abc",则 JVM 会在常量池中创建该字符串字面量并返回它的引用。
737+
// 这个引用被压入操作数栈,用作构造函数的参数。
738+
4 ldc #3 <abc>
739+
// 调用构造方法,使用从常量池中加载的 "abc" 初始化堆中的 String 对象
740+
// 新的 String 对象将包含与常量池中的 "abc" 相同的内容,但它是一个独立的对象,存储于堆中。
741+
6 invokespecial #4 <java/lang/String.<init> : (Ljava/lang/String;)V>
742+
// 将堆中的 String 对象引用存储到局部变量表
743+
9 astore_1
744+
// 返回,结束方法
745+
10 return
746+
```
722747
723-
`ldc (load constant)` 指令的作用是从常量池中加载常量,包括字符串常量、整数常量、浮点数常量、或者类引用。这里用于判断字符串常量池中是否保存了对应的字符串对象,如果保存了的话会将它的引用加载到操作数栈,如果没有保存的话,会在字符串常量池中创建对应的字符串对象,并将其引用加载到操作数栈中。
748+
`ldc (load constant)` 指令的确是从常量池中加载各种类型的常量,包括字符串常量、整数常量、浮点数常量,甚至类引用等。对于字符串常量,`ldc` 指令的行为如下:
749+
750+
1. **从常量池加载字符串**:`ldc` 首先检查字符串常量池中是否已经有内容相同的字符串对象。
751+
2. **复用已有字符串对象**:如果字符串常量池中已经存在内容相同的字符串对象,`ldc` 会将该对象的引用加载到操作数栈上。
752+
3. **没有则创建新对象并加入常量池**:如果字符串常量池中没有相同内容的字符串对象,JVM 会在常量池中创建一个新的字符串对象,并将其引用加载到操作数栈中。
724753
725754
2、如果字符串常量池中已存在字符串对象“abc”,则只会在堆中创建 1 个字符串对象“abc”。
726755
@@ -735,7 +764,16 @@ String s2 = new String("abc");
735764
736765
对应的字节码:
737766
738-
![](https://oss.javaguide.cn/github/javaguide/open-source-project/image-20220413180021072.png)
767+
```java
768+
0 ldc #2 <abc>
769+
2 astore_1
770+
3 new #3 <java/lang/String>
771+
6 dup
772+
7 ldc #2 <abc>
773+
9 invokespecial #4 <java/lang/String.<init> : (Ljava/lang/String;)V>
774+
12 astore_2
775+
13 return
776+
```
739777
740778
这里就不对上面的字节码进行详细注释了,7 这个位置的 `ldc` 命令不会在堆中创建新的字符串对象“abc”,这是因为 0 这个位置已经执行了一次 `ldc` 命令,已经在堆中创建过一次字符串对象“abc”了。7 这个位置执行 `ldc` 命令会直接返回字符串常量池中字符串对象“abc”对应的引用。
741779

docs/java/basis/java-basic-questions-03.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ head:
5555

5656
### Throwable 类常用方法有哪些?
5757

58-
- `String getMessage()`: 返回异常发生时的简要描述
59-
- `String toString()`: 返回异常发生时的详细信息
58+
- `String getMessage()`: 返回异常发生时的详细信息
59+
- `String toString()`: 返回异常发生时的简要描述
6060
- `String getLocalizedMessage()`: 返回异常对象的本地化信息。使用 `Throwable` 的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与 `getMessage()`返回的结果相同
6161
- `void printStackTrace()`: 在控制台上打印 `Throwable` 对象封装的异常信息
6262

docs/java/concurrent/completablefuture-intro.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,15 @@ abc
653653

654654
我们上面的代码示例中,为了方便,都没有选择自定义线程池。实际项目中,这是不可取的。
655655

656-
`CompletableFuture` 默认使用`ForkJoinPool.commonPool()` 作为执行器,这个线程池是全局共享的,可能会被其他任务占用,导致性能下降或者饥饿。因此,建议使用自定义的线程池来执行 `CompletableFuture` 的异步任务,可以提高并发度和灵活性。
656+
`CompletableFuture` 默认使用全局共享的 `ForkJoinPool.commonPool()` 作为执行器,所有未指定执行器的异步任务都会使用该线程池。这意味着应用程序、多个库或框架(如 Spring、第三方库)若都依赖 `CompletableFuture`,默认情况下它们都会共享同一个线程池。
657+
658+
虽然 `ForkJoinPool` 效率很高,但当同时提交大量任务时,可能会导致资源竞争和线程饥饿,进而影响系统性能。
659+
660+
为避免这些问题,建议为 `CompletableFuture` 提供自定义线程池,带来以下优势:
661+
662+
- **隔离性**:为不同任务分配独立的线程池,避免全局线程池资源争夺。
663+
- **资源控制**:根据任务特性调整线程池大小和队列类型,优化性能表现。
664+
- **异常处理**:通过自定义 `ThreadFactory` 更好地处理线程中的异常情况。
657665

658666
```java
659667
private ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10,

0 commit comments

Comments
 (0)