Skip to content

Commit f34c5ef

Browse files
committed
docs: 更新文档
1 parent eb7fac5 commit f34c5ef

11 files changed

+438
-58
lines changed
-9.75 KB
Binary file not shown.

assets/Java/JavaCore/Java_IO.xmind

-36 Bytes
Binary file not shown.

assets/Java/JavaCore/Java_QA.xmind

79.8 KB
Binary file not shown.
34 KB
Binary file not shown.
18.4 KB
Binary file not shown.
41.9 KB
Binary file not shown.

docs/01.Java/JavaCore/面试/Java_面试_基础(一).md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,12 @@ System.out.println(a == b); // false
511511

512512
### 【简单】如何解决浮点数运算的精度丢失问题?
513513

514+
**首选 BigDecimal **表示需要保证精度的场景,如:金融数值。
515+
516+
- 构造必用字符串 / 整数,禁用 double;
517+
- 运算用`add/subtract/multiply/divide`方法;
518+
- 除法必须指定精度和舍入模式(避免除不尽报错)。
519+
514520
`BigDecimal` 直接使用字符串初始化(如 `new BigDecimal("0.1")`)可完全避免二进制浮点误差。通常情况下,大部分需要浮点数精确运算结果的业务场景(比如涉及到钱的场景)可以通过 `BigDecimal` 来处理。
515521

516522
```java
@@ -526,6 +532,8 @@ System.out.println(y); /* 0.1 */
526532
System.out.println(Objects.equals(x, y)); /* true */
527533
```
528534

535+
简单场景,可用**放大整数运算**:将小数放大为整数,如使用 long 表示金钱,单位为分
536+
529537
### 【简单】超过 long 整型的数据应该如何表示?
530538

531539
基本数值类型都有一个表达范围,如果超过这个范围就会有数值溢出的风险。
@@ -538,7 +546,7 @@ System.out.println(l + 1); // -9223372036854775808
538546
System.out.println(l + 1 == Long.MIN_VALUE); // true
539547
```
540548

541-
`BigInteger` 内部使用 `int[]` 数组来存储任意大小的整形数据。
549+
**`BigInteger` 内部使用 `int[]` 数组来存储任意大小的整形数据**
542550

543551
相对于常规整数类型的运算来说,`BigInteger` 运算的效率会相对较低。
544552

@@ -1120,4 +1128,4 @@ catch (IOException e) {
11201128

11211129
**一句话总结**`final`**不变性**`finally`**必执行**`finalize`**过时的清理机制**
11221130

1123-
(注:现代 Java 开发用`try-with-resources`替代`finalize`
1131+
(注:现代 Java 开发用`try-with-resources`替代`finalize`

docs/01.Java/JavaCore/面试/Java_面试_基础(二).md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ Java 中的类可以实现多个接口。
6161
::: info 什么是内部类?
6262
:::
6363

64-
内部类 (Inner Class) 是定义在另一个类内部的类。Java 中有四种类型的内部类:
64+
内部类 (Inner Class) 是定义在另一个类内部的类 .java 中有四种类型的内部类:
6565

6666
- **成员内部类**:作为外部类的成员存在
6767
- **局部内部类**:定义在方法或作用域内的类
@@ -82,7 +82,7 @@ Java 中的类可以实现多个接口。
8282

8383
- 内部类可以访问外部类的所有成员(包括 private)
8484
- 外部类需要通过实例化内部类来访问其成员
85-
- 内部类编译后会生成独立的class 文件(格式:`OuterClass$InnerClass.class`)
85+
- 内部类编译后会生成独立的 .class 文件(格式:`OuterClass$InnerClass.class`)
8686
- 非静态内部类不能有静态成员(静态内部类可以)
8787
- 内部类可以继承其他类或实现接口
8888

docs/01.Java/JavaCore/面试/Java_面试_并发(三).md

Lines changed: 126 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,7 @@ Thread-4 占用资源
897897

898898
## Java 并发分工工具
899899

900-
### 【中等ForkJoinPool 的工作原理是什么?⭐⭐
900+
### 【困难ForkJoinPool 的工作原理是什么?⭐⭐
901901

902902
ForkJoinPool 是专为**分治任务**设计的线程池,核心作用是将大任务拆分为小任务并行执行,再合并结果。
903903

@@ -949,7 +949,24 @@ ForkJoinPool 基于 “分治 + 工作窃取” 算法,让空闲线程偷取
949949
| **任务调度** | 任务窃取(本地队列+窃取) | 全局队列(可能竞争) |
950950
| **适用场景** | CPU 密集型并行计算 | IO 密集型或短任务 |
951951

952-
### 【中等】CompleteFuture 的工作原理是什么?⭐
952+
### 【中等】CompleteFuture 有哪些用法?
953+
954+
CompletableFutureJava 8+ 提供的**异步任务编排工具**
955+
956+
| 用法类型 | 核心方法(记忆关键词) | 作用说明 | 示例代码 |
957+
| :------------------ | :----------------------------------------------------------- | :-------------------------------------------- | :----------------------------------------------------------- |
958+
| **创建异步任务** | `runAsync`(无返回值)<br/>`supplyAsync`(有返回值) | 提交异步任务,指定线程池(默认 ForkJoinPool| `// 有返回值异步任务<br>CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> "Hello", executor);` |
959+
| **结果转换** | `thenApply`(同步)<br/>`thenApplyAsync`(异步) | 对任务结果做转换,返回新结果 | `cf.thenApply(s -> s + " World");` |
960+
| **结果消费** | `thenAccept`(同步)<br/>`thenAcceptAsync`(异步) | 消费任务结果(无返回值) | `cf.thenAccept(s -> System.out.println(s));` |
961+
| **任务衔接** | `thenRun`(同步)<br/>`thenRunAsync`(异步) | 任务完成后执行无参操作(不依赖结果) | `cf.thenRun(() -> System.out.println("任务完成"));` |
962+
| **多任务合并** | `allOf`(全部完成)<br/>`anyOf`(任一完成) | 等待任务完成 | `CompletableFuture.allOf(cf1, cf2).join();`<br/>`Object result = CompletableFuture.anyOf(cf1, cf2).get();` |
963+
| **结果组合** | `thenCombinethenCombineAsync` | 合并两个任务的结果,生成新结果 | `cf1.thenCombine(cf2, (r1, r2) -> r1 + r2);` |
964+
| **异常处理** | `exceptionally` | 任务异常时返回默认值 | `cf.exceptionally(e -> "默认值");` |
965+
| **异常 / 完成处理** | `whenComplete` | 无论成功 / 失败,都执行回调(可获取异常) | `cf.whenComplete((res, e) -> { if(e!=null) e.printStackTrace(); });` |
966+
| **超时控制** | `completeOnTimeoutorTimeout` | 超时后返回默认值 / 抛出超时异常 | `// 3秒超时返回默认值<br>cf.completeOnTimeout("超时默认值", 3, TimeUnit.SECONDS);` |
967+
| **结果获取** | `get`(阻塞)<br/>`join`(阻塞,不抛检查异常)<br/>`getNow`(立即获取,无结果返回默认值) | 获取任务结果,按需选择阻塞 / 非阻塞 | `String res = cf.join(); // 推荐,无需捕获异常` |
968+
969+
### 【困难】CompleteFuture 的工作原理是什么?⭐
953970

954971
CompletableFuture 基于「状态机 + 回调链表」实现的异步编程框架。
955972

@@ -1096,9 +1113,114 @@ JDK 内置的三种实现定时器的方式,实现思路都非常相似,都
10961113

10971114
HashedWheelTimerNetty 中时间轮算法的实现类。
10981115

1099-
## 案例
1116+
## Java 并发应用
1117+
1118+
### 【中等】Java 中如何控制多线程的执行顺序?
1119+
1120+
Java 控制多线程执行顺序,核心是通过「阻塞等待」「同步控制」「任务编排」三类机制,打破线程调度的随机性,让线程按指定顺序(如 ABC)执行,本质是控制线程的执行时机和先后依赖。
1121+
1122+
| 方法类型 | 核心 API(记忆关键词) | 实现原理 | 适用场景 |
1123+
| :--------------------------------------------------- | :----------------------------------------------------------- | :----------------------------------------------------------- | :--------------------------------------------------------- |
1124+
| join () 等待(最基础) | Thread.join() | 让当前线程阻塞,等待目标线程执行完成后再继续 | 简单顺序(如 A 执行完再执行 B)、少量线程 |
1125+
|+ 信号量(手动控制) | synchronized + 标志位CountDownLatch(倒计时门闩) | ① 标志位:线程循环检查前置条件;② CountDownLatch:等待计数器归 0 | 多线程分批次执行(如先执行所有初始化线程,再执行业务线程) |
1126+
| 线程池按序执行 | Executors.newSingleThreadExecutor() | 单线程池串行执行提交的任务,底层基于队列 FIFO | 任务需严格按提交顺序执行,无需并行 |
1127+
| CompletableFuture 编排(推荐) | thenRun/thenAccept/thenApply | 异步任务链式编排,前一个任务完成自动执行下一个 | 复杂顺序(如 AB 并行 CD)、异步场景 |
1128+
| 同步工具(CountDownLatchCyclicBarrierSemaphore| CountDownLatch.await()/countDown()<br/>CyclicBarrier.await()<br/>Semaphore.acquire()/release() | 底层直接或间接基于 AQS 实现 | 多线程先准备再统一执行(如多线程加载数据后,统一处理) |
1129+
1130+
::: code-tabs#控制多线程的执行顺序
1131+
1132+
@tab join () 控制顺序
1133+
1134+
`join()` 是线程级 别的阻塞,目标线程执行完才会释放当前线程。
1135+
1136+
```java
1137+
// 定义3个线程
1138+
Thread t1 = new Thread(() -> System.out.println("线程A执行"), "A");
1139+
Thread t2 = new Thread(() -> System.out.println("线程B执行"), "B");
1140+
Thread t3 = new Thread(() -> System.out.println("线程C执行"), "C");
1141+
1142+
// 控制顺序:A→B→C
1143+
t1.start();
1144+
t1.join(); // 主线程等待t1完成
1145+
t2.start();
1146+
t2.join(); // 主线程等待t2完成
1147+
t3.start();
1148+
```
1149+
1150+
@tab CountDownLatch 分批次执行
1151+
1152+
计数器归 0 前,`await()` 线程阻塞,适合 “先完成前置任务,再执行主任务”。
1153+
1154+
```java
1155+
// 倒计时门闩:计数器为2,需2个初始化线程完成
1156+
CountDownLatch latch = new CountDownLatch(2);
1157+
1158+
// 初始化线程1
1159+
Thread init1 = new Thread(() -> {
1160+
System.out.println("初始化1完成");
1161+
latch.countDown(); // 计数器-1
1162+
});
1163+
// 初始化线程2
1164+
Thread init2 = new Thread(() -> {
1165+
System.out.println("初始化2完成");
1166+
latch.countDown(); // 计数器-1
1167+
});
1168+
// 业务线程(需等初始化完成)
1169+
Thread business = new Thread(() -> {
1170+
try {
1171+
latch.await(); // 阻塞直到计数器=0
1172+
System.out.println("业务线程执行");
1173+
} catch (InterruptedException e) {
1174+
Thread.currentThread().interrupt();
1175+
}
1176+
});
1177+
1178+
// 启动顺序不影响,业务线程会等初始化完成
1179+
init1.start();
1180+
init2.start();
1181+
business.start();
1182+
```
1183+
1184+
@tab CompletableFuture 链式编排
1185+
1186+
链式调用天然支持顺序,`thenRunAsync` 保证前序任务完成后执行,适合复杂编排。
1187+
1188+
```java
1189+
// 自定义线程池(避免默认池)
1190+
ExecutorService executor = Executors.newFixedThreadPool(3);
1191+
1192+
// 顺序:A完成→B和C并行→D完成
1193+
CompletableFuture<Void> cf = CompletableFuture
1194+
.runAsync(() -> System.out.println("任务A执行"), executor) // 第一步:A
1195+
.thenRunAsync(() -> System.out.println("任务B执行"), executor) // 第二步:A完成后执行B
1196+
.thenRunAsync(() -> { // 第三步:B完成后,并行执行C
1197+
CompletableFuture.runAsync(() -> System.out.println("任务C执行"), executor).join();
1198+
}, executor)
1199+
.thenRunAsync(() -> System.out.println("任务D执行"), executor); // 第四步:C完成后执行D
1200+
1201+
cf.join(); // 等待所有任务完成
1202+
executor.shutdown();
1203+
```
1204+
1205+
@tab 单线程池按提交顺序执行
1206+
1207+
无需手动控制,池内队列保证 FIFO,适合简单串行场景。
1208+
1209+
```java
1210+
// 单线程池:任务按提交顺序串行执行
1211+
ExecutorService singleExecutor = Executors.newSingleThreadExecutor();
1212+
1213+
// 提交顺序=执行顺序:A→B→C
1214+
singleExecutor.submit(() -> System.out.println("任务A执行"));
1215+
singleExecutor.submit(() -> System.out.println("任务B执行"));
1216+
singleExecutor.submit(() -> System.out.println("任务C执行"));
1217+
1218+
singleExecutor.shutdown();
1219+
```
1220+
1221+
:::
11001222

1101-
### 生产者消费者模式
1223+
### 【中等】Java 中如何实现生产者消费者模式?
11021224

11031225
**经典问题**
11041226

0 commit comments

Comments
 (0)