Skip to content

Commit deeef21

Browse files
committed
docs: improve wording of README and javadoc 📚
1 parent 01b1a4d commit deeef21

File tree

11 files changed

+140
-55
lines changed

11 files changed

+140
-55
lines changed

README.md

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@
6565
☘️ **补全业务使用中缺失的功能**
6666

6767
- 🏪 更方便的功能,如
68-
- 支持返回多个输入`CF`的运行结果,而不是返回没有包含输入`CF`结果`CompletableFuture#allOf`
68+
- 支持返回多个输入`CF`的运行结果,而不是返回没有包含输入`CF`的结果`CompletableFuture#allOf`
6969
如方法`allResultsFailFastOf` / `allResultsOf` / `mSupplyFailFastAsync` / `thenMApplyFailFastAsync`
70-
- 支持返回多个不同类型的输入`CF`结果,而不是同一类型
70+
- 支持返回多个不同类型的输入`CF`的结果,而不是同一类型
7171
如方法`allTupleFailFastOf` / `allTupleOf` / `mSupplyTupleFailFastAsync` / `thenMApplyTupleFailFastAsync`
7272
- 支持直接运行多个`Action`,而不是要先包装成`CompletableFuture`
73-
如方法`mSupplyTupleFailFastAsync` / `mSupplyMostSuccessAsync` / `thenMApplyTupleFailFastAsync` / `thenMRunFailFastAsync`
73+
如方法`mSupplyAsync` / `mRunAsync` / `mSupplyFailFastAsync` / `thenMApplyMostSuccessTupleAsync`
7474
- 支持设置缺省的业务线程池并封装携带,`CffuFactory#builder(executor)`方法,而不是在异步执行时反复传入业务线程池参数
7575
- 支持处理指定异常类型的`catching`方法,而不是处理所有异常`Throwable``CompletableFuture#exceptionally`
7676
- 🚦 更高效灵活的并发执行策略,如
@@ -90,7 +90,7 @@
9090
`@NonNull``@Nullable``@CheckReturnValue``@Contract`
9191
- 🧩 缺失的基本功能,除了上面面向安全而新实现的方法,还有
9292
- 异步异常完成,`completeExceptionallyAsync`方法
93-
- 非阻塞地获取成功结果,如果`CF`失败或还在运行中则返回指定的缺省值,`getSuccessNow`方法
93+
- 非阻塞地获取成功结果,对于`CF`失败或还在运行中则返回指定的缺省值,`getSuccessNow`方法
9494
- 解包装`CF`异常成业务异常,`unwrapCfException`方法
9595

9696
**`Backport`支持`Java 8`**`Java 9+`高版本的所有`CF`新功能方法在`Java 8`低版本直接可用,如
@@ -155,7 +155,7 @@
155155
如果你不想在项目中引入新类(`Cffu`类)、觉得这样增加了复杂性的话,完全可以将`cffu`库作为一个工具类来用:
156156

157157
- 优化`CompletableFuture`使用的工具方法在业务项目中很常见
158-
- `CompletableFutureUtils`提供了一系列实用可靠高效安全的工具方法
158+
- `CompletableFutureUtils`提供了一系列实用高效安全可靠的工具方法
159159
- 这种使用方式有些`cffu`功能没有提供(也没有想到好的实现方案)
160160
如支持设置缺省的业务线程池、禁止强制篡改
161161

@@ -175,7 +175,7 @@
175175
> - `CompletableFuture`类的所有实例方法都在`Cffu`类中有实现,且有相同的方法签名与功能
176176
> - `CompletableFuture`类的所有静态方法都在`CffuFactory`类中有实现,且有相同的方法签名与功能
177177
178-
2\) 如果不能修改使用`CompletableFuture`的代码(如其它库返回的`CF`
178+
2\) 如果不能修改使用`CompletableFuture`的代码(如在外部库中返回的`CF`
179179

180180
使用[`CffuFactory.toCffu(CompletionStage)`方法](https://foldright.io/api-docs/cffu/1.1.0/io/foldright/cffu/CffuFactory.html#toCffu(java.util.concurrent.CompletionStage)),将`CompletableFuture``CompletionStage`转换成`Cffu`类型。
181181

@@ -232,8 +232,8 @@
232232

233233
```java
234234
public class AllResultsOfDemo {
235-
public static final Executor myBizExecutor = Executors.newCachedThreadPool();
236-
public static final CffuFactory cffuFactory = CffuFactory.builder(myBizExecutor).build();
235+
private static final ExecutorService myBizExecutor = Executors.newCachedThreadPool();
236+
private static final CffuFactory cffuFactory = CffuFactory.builder(myBizExecutor).build();
237237

238238
public static void main(String[] args) throws Exception {
239239
//////////////////////////////////////////////////
@@ -276,8 +276,8 @@ public class AllResultsOfDemo {
276276

277277
```java
278278
public class AllTupleOfDemo {
279-
public static final Executor myBizExecutor = Executors.newCachedThreadPool();
280-
public static final CffuFactory cffuFactory = CffuFactory.builder(myBizExecutor).build();
279+
private static final ExecutorService myBizExecutor = Executors.newCachedThreadPool();
280+
private static final CffuFactory cffuFactory = CffuFactory.builder(myBizExecutor).build();
281281

282282
public static void main(String[] args) throws Exception {
283283
//////////////////////////////////////////////////
@@ -351,8 +351,8 @@ public class NoDefaultExecutorSettingForCompletableFuture {
351351

352352
```java
353353
public class DefaultExecutorSettingForCffu {
354-
public static final Executor myBizExecutor = Executors.newCachedThreadPool();
355-
public static final CffuFactory cffuFactory = CffuFactory.builder(myBizExecutor).build();
354+
private static final ExecutorService myBizExecutor = Executors.newCachedThreadPool();
355+
private static final CffuFactory cffuFactory = CffuFactory.builder(myBizExecutor).build();
356356

357357
public static void main(String[] args) {
358358
Cffu<Void> cf1 = cffuFactory.runAsync(() -> System.out.println("doing a long time work!"));
@@ -372,7 +372,7 @@ public class DefaultExecutorSettingForCffu {
372372
### 2.3 高效灵活的并发执行策略(`AllFailFast` / `AnySuccess` / `AllSuccess` / `MostSuccess`
373373

374374
- `CompletableFuture``allOf`方法会等待所有输入`CF`运行完成;即使有`CF`失败了也要等待后续`CF`都运行完成,再返回一个失败的`CF`
375-
- 对于业务逻辑来说,这样失败且继续等待的策略(`AllComplete`),减慢了业务响应性;会希望如果有输入`CF`失败了,则快速失败不再做于事无补的等待
375+
- 对于业务逻辑来说,这样失败且继续等待的策略(`AllComplete`),减慢了业务响应性;会希望当有输入`CF`失败了,则快速失败不再做于事无补的等待
376376
- `cffu`提供了相应的`allResultsFailFastOf`等方法,支持`AllFailFast`并发执行策略
377377
- `allOf` / `allResultsFailFastOf`两者都是,只有当所有的输入`CF`都成功时,才返回成功结果
378378
- `CompletableFuture``anyOf`方法返回首个完成的`CF`,不会等待后续没有完成的`CF`赛马模式;即使首个完成的`CF`是失败的,也会返回这个失败的`CF`结果。
@@ -403,8 +403,8 @@ public class DefaultExecutorSettingForCffu {
403403

404404
```java
405405
public class ConcurrencyStrategyDemo {
406-
public static final Executor myBizExecutor = Executors.newCachedThreadPool();
407-
public static final CffuFactory cffuFactory = CffuFactory.builder(myBizExecutor).build();
406+
private static final ExecutorService myBizExecutor = Executors.newCachedThreadPool();
407+
private static final CffuFactory cffuFactory = CffuFactory.builder(myBizExecutor).build();
408408

409409
public static void main(String[] args) throws Exception {
410410
////////////////////////////////////////////////////////////////////////
@@ -507,6 +507,9 @@ public class MultipleActionsDemo {
507507

508508
```java
509509
public class MultipleActionsDemo {
510+
private static final ExecutorService myBizExecutor = Executors.newCachedThreadPool();
511+
private static final CffuFactory cffuFactory = CffuFactory.builder(myBizExecutor).build();
512+
510513
static void thenMApplyAsyncDemo() {
511514
// wrap tasks to CompletableFuture first, AWKWARD! 😖
512515
completedFuture(42).thenCompose(v ->
@@ -517,6 +520,14 @@ public class MultipleActionsDemo {
517520
)
518521
).thenAccept(System.out::println);
519522
// output: [43, 44, 45]
523+
cffuFactory.completedFuture(42).thenCompose(v ->
524+
CompletableFutureUtils.allResultsFailFastOf(
525+
CompletableFuture.supplyAsync(() -> v + 1),
526+
CompletableFuture.supplyAsync(() -> v + 2),
527+
CompletableFuture.supplyAsync(() -> v + 3)
528+
)
529+
).thenAccept(System.out::println);
530+
// output: [43, 44, 45]
520531

521532
// just run multiple actions, fresh and cool 😋
522533
CompletableFutureUtils.thenMApplyFailFastAsync(
@@ -526,13 +537,26 @@ public class MultipleActionsDemo {
526537
v -> v + 3
527538
).thenAccept(System.out::println);
528539
// output: [43, 44, 45]
529-
CompletableFutureUtils.thenMApplyTupleFailFastAsync(
540+
cffuFactory.completedFuture(42).thenMApplyFailFastAsync(
541+
v -> v + 1,
542+
v -> v + 2,
543+
v -> v + 3
544+
).thenAccept(System.out::println);
545+
// output: [43, 44, 45]
546+
547+
CompletableFutureUtils.thenMApplyAllSuccessTupleAsync(
530548
completedFuture(42),
531549
v -> "string" + v,
532550
v -> v + 1,
533551
v -> v + 2.1
534552
).thenAccept(System.out::println);
535553
// output: Tuple3(string42, 43, 44.1)
554+
cffuFactory.completedFuture(42).thenMApplyAllSuccessTupleAsync(
555+
v -> "string" + v,
556+
v -> v + 1,
557+
v -> v + 2.1
558+
).thenAccept(System.out::println);
559+
// output: Tuple3(string42, 43, 44.1)
536560
}
537561
}
538562
```
@@ -584,6 +608,7 @@ public class MultipleActionsDemo {
584608
- 演示问题的[`DelayDysfunctionDemo.java`](https://github.com/foldright/cffu/blob/main/cffu-core/src/test/java/io/foldright/demo/CfDelayDysfunctionDemo.java)
585609
- `cffu backport`方法的`JavaDoc`[`CFU#orTimeout()`](https://foldright.io/api-docs/cffu/1.1.0/io/foldright/cffu/CompletableFutureUtils.html#orTimeout(C,long,java.util.concurrent.TimeUnit))
586610
/ [`CFU#completeOnTimeout()`](https://foldright.io/api-docs/cffu/1.1.0/io/foldright/cffu/CompletableFutureUtils.html#completeOnTimeout(C,T,long,java.util.concurrent.TimeUnit))
611+
- 文章[`CompletableFuture`超时功能使用不当直接生产事故](https://juejin.cn/post/7411686792342274089)
587612

588613
### 2.8 支持超时的`join`方法
589614

@@ -598,7 +623,7 @@ public class MultipleActionsDemo {
598623

599624
### 2.9 返回具体类型的`anyOf`方法
600625

601-
`CompletableFuture``anyOf()`方法返回类型是`Object`,丢失具体类型,不类型安全;使用返回值时需要转型也不方便
626+
`CompletableFuture``anyOf()`方法返回类型是`Object`,丢失具体类型,使用返回值时需要转型操作不方便,也不类型安全
602627

603628
`cffu`提供的`anySuccessOf()` / `anyOf()`方法,返回具体类型`T`,而不是返回`Object`
604629

cffu-core/src/main/java/io/foldright/cffu/Cffu.java

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,15 +1673,19 @@ public Cffu<T> orTimeout(long timeout, TimeUnit unit) {
16731673
* <p>
16741674
* <strong>CAUTION:</strong> This method is <strong>UNSAFE</strong>!
16751675
* <p>
1676-
* When the wait timed out, the subsequent non-async actions of the dependent CompletableFutures are performed
1676+
* When the wait timed out, the subsequent non-async actions of the dependent Cffus/CompletableFutures are performed
16771677
* in CompletableFuture's internal <strong>SINGLE-thread delay executor</strong> (including timeout functionality).
16781678
* This means that the long-running subsequent non-async actions will block this executor thread, preventing it from
16791679
* handling other timeouts and delays, effectively breaking CompletableFuture's timeout and delay functionality.
16801680
* <p>
16811681
* <strong>Strongly recommend</strong> using the safe method {@link #orTimeout(long, TimeUnit)} instead of this method.
1682-
* <br>The only case where using this method makes sense is when all subsequent actions of dependent Cffus
1683-
* are guaranteed to execute asynchronously (i.e. the dependent Cffus are created by async methods).
1684-
* In this case, they save one thread switch when the timeout triggers.
1682+
* Using this method is appropriate only when either:
1683+
* <ul>
1684+
* <li>the returned Cffu is read in a blocking manner, or
1685+
* <li>all subsequent actions of dependent Cffus/CompletableFutures are guaranteed to execute asynchronously
1686+
* (i.e., the dependent Cffus/CompletableFutures are created using async methods).
1687+
* </ul> In these cases, using these methods avoids an unnecessary thread switch when timeout occurs; However,
1688+
* these conditions are difficult to guarantee in practice especially when the returned Cffu is used by other code.
16851689
* <p>
16861690
* Note: Before Java 21(Java 20-), {@link CompletableFuture#orTimeout} leaks if the future completes exceptionally,
16871691
* more info see <a href="https://bugs.openjdk.org/browse/JDK-8303742">issue JDK-8303742</a>,
@@ -1729,15 +1733,20 @@ public Cffu<T> completeOnTimeout(@Nullable T value, long timeout, TimeUnit unit)
17291733
* <p>
17301734
* <strong>CAUTION:</strong> This method is <strong>UNSAFE</strong>!
17311735
* <p>
1732-
* When the wait timed out, the subsequent non-async actions of the dependent CompletableFutures are performed
1736+
* When the wait timed out, the subsequent non-async actions of the dependent Cffus/CompletableFutures are performed
17331737
* in CompletableFuture's internal <strong>SINGLE-thread delay executor</strong> (including timeout functionality).
17341738
* This means that the long-running subsequent non-async actions will block this executor thread, preventing it from
17351739
* handling other timeouts and delays, effectively breaking CompletableFuture's timeout and delay functionality.
17361740
* <p>
17371741
* <strong>Strongly recommend</strong> using the safe method {@link #completeOnTimeout(Object, long, TimeUnit)}
1738-
* instead of this method.<br>The only case where using this method makes sense is when all subsequent actions of
1739-
* dependent Cffus are guaranteed to execute asynchronously (i.e. the dependent Cffus are created by async methods).
1740-
* In this case, they save one thread switch when the timeout triggers.
1742+
* instead of this method.
1743+
* Using this method is appropriate only when either:
1744+
* <ul>
1745+
* <li>the returned Cffu is read in a blocking manner, or
1746+
* <li>all subsequent actions of dependent Cffus/CompletableFutures are guaranteed to execute asynchronously
1747+
* (i.e., the dependent Cffus/CompletableFutures are created using async methods).
1748+
* </ul> In these cases, using these methods avoids an unnecessary thread switch when timeout occurs; However, these
1749+
* conditions are difficult to guarantee in practice especially when the returned Cffu is used by other code.
17411750
*
17421751
* @param value the value to use upon timeout
17431752
* @param timeout how long to wait before completing normally with the given value, in units of {@code unit}
@@ -2238,6 +2247,10 @@ public T join() {
22382247
* Waits if necessary for at most the given time for the computation to complete,
22392248
* and then retrieves its result value when complete, or throws an (unchecked) exception if completed exceptionally.
22402249
* <p>
2250+
* <strong>CAUTION:</strong> if the wait timed out, this method throws an (unchecked) {@link CompletionException}
2251+
* with the {@link TimeoutException} as its cause;
2252+
* NOT throws a (checked) {@link TimeoutException} like {@link #get(long, TimeUnit)}.
2253+
* <p>
22412254
* <strong>NOTE:</strong> Calling this method
22422255
* <p>
22432256
* {@code result = cffu.join(timeout, unit);}
@@ -2249,10 +2262,6 @@ public T join() {
22492262
* .join();
22502263
* }</pre>
22512264
*
2252-
* <strong>CAUTION:</strong> if the wait timed out, this method throws an (unchecked) {@link CompletionException}
2253-
* with the {@link TimeoutException} as its cause;
2254-
* NOT throws a (checked) {@link TimeoutException} like {@link #get(long, TimeUnit)}.
2255-
*
22562265
* @param timeout the maximum time to wait
22572266
* @param unit the time unit of the timeout argument
22582267
* @return the result value

0 commit comments

Comments
 (0)