@@ -897,7 +897,7 @@ Thread-4 占用资源
897897
898898## Java 并发分工工具
899899
900- ### 【中等 】ForkJoinPool 的工作原理是什么?⭐⭐
900+ ### 【困难 】ForkJoinPool 的工作原理是什么?⭐⭐
901901
902902ForkJoinPool 是专为** 分治任务** 设计的线程池,核心作用是将大任务拆分为小任务并行执行,再合并结果。
903903
@@ -949,7 +949,24 @@ ForkJoinPool 基于 “分治 + 工作窃取” 算法,让空闲线程偷取
949949| ** 任务调度** | 任务窃取(本地队列+ 窃取) | 全局队列(可能竞争) |
950950| ** 适用场景** | CPU 密集型并行计算 | IO 密集型或短任务 |
951951
952- ### 【中等】CompleteFuture 的工作原理是什么?⭐
952+ ### 【中等】CompleteFuture 有哪些用法?
953+
954+ CompletableFuture 是 Java 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
954971CompletableFuture 基于「状态机 + 回调链表」实现的异步编程框架。
955972
@@ -1096,9 +1113,114 @@ JDK 内置的三种实现定时器的方式,实现思路都非常相似,都
10961113
10971114HashedWheelTimer 是 Netty 中时间轮算法的实现类。
10981115
1099- ## 案例
1116+ ## Java 并发应用
1117+
1118+ ### 【中等】Java 中如何控制多线程的执行顺序?
1119+
1120+ Java 控制多线程执行顺序,核心是通过「阻塞等待」「同步控制」「任务编排」三类机制,打破线程调度的随机性,让线程按指定顺序(如 A →B →C )执行,本质是控制线程的执行时机和先后依赖。
1121+
1122+ | 方法类型 | 核心 API (记忆关键词) | 实现原理 | 适用场景 |
1123+ | : -------------------------------------------------- - | : ---------------------------------------------------------- - | : ---------------------------------------------------------- - | : -------------------------------------------------------- - |
1124+ | join () 等待(最基础) | Thread . join() | 让当前线程阻塞,等待目标线程执行完成后再继续 | 简单顺序(如 A 执行完再执行 B )、少量线程 |
1125+ | 锁 + 信号量(手动控制) | synchronized + 标志位CountDownLatch (倒计时门闩) | ① 标志位:线程循环检查前置条件;② CountDownLatch :等待计数器归 0 | 多线程分批次执行(如先执行所有初始化线程,再执行业务线程) |
1126+ | 线程池按序执行 | Executors . newSingleThreadExecutor() | 单线程池串行执行提交的任务,底层基于队列 FIFO | 任务需严格按提交顺序执行,无需并行 |
1127+ | CompletableFuture 编排(推荐) | thenRun/ thenAccept/ thenApply | 异步任务链式编排,前一个任务完成自动执行下一个 | 复杂顺序(如 A →B 并行 C →D )、异步场景 |
1128+ | 同步工具(CountDownLatch 、CyclicBarrier 、Semaphore ) | 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