Skip to content

Commit

Permalink
docs: improve readme and apidoc 📚
Browse files Browse the repository at this point in the history
  • Loading branch information
oldratlee committed Apr 24, 2024
1 parent f6d8c7e commit c273229
Show file tree
Hide file tree
Showing 15 changed files with 96 additions and 89 deletions.
68 changes: 35 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
- 当然基本的并发关注方面及其复杂性,与具体使用哪个工具无关,都是要理解与注意的
- **高层抽象**
- 或说 以业务流程的形式表达技术的并发流程
- 可以不使用繁琐易错的基础并发协调工具,[`CountDownLatch`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/CountDownLatch.html)、锁([`Lock`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/locks/package-summary.html)、信号量([`Semaphore`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/Semaphore.html)
- 可以不使用繁琐易错的基础并发协调工具,如锁([`Lock`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/locks/package-summary.html))、[`CountDownLatch`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/CountDownLatch.html)、信号量([`Semaphore`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/Semaphore.html)[`CyclicBarrier`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/CyclicBarrier.html)

和其它并发工具、框架一样,`CompletableFuture`用于

Expand Down Expand Up @@ -182,6 +182,7 @@ public class CffuDemo {
final Cffu<Integer> combined = longTaskA.thenCombine(longTaskB, Integer::sum)
.orTimeout(1500, TimeUnit.MILLISECONDS);
System.out.println("combined result: " + combined.get());

final Cffu<Integer> anyOfSuccess = cffuFactory.anyOfSuccess(longTaskC, longFailedTask);
System.out.println("anyOfSuccess result: " + anyOfSuccess.get());
}
Expand Down Expand Up @@ -219,9 +220,11 @@ public class CompletableFutureUtilsDemo {
}, myBizThreadPool);

final CompletableFuture<Integer> combined = longTaskA.thenCombine(longTaskB, Integer::sum);
final CompletableFuture<Integer> combinedWithTimeout = CompletableFutureUtils.orTimeout(combined, 1500, TimeUnit.MILLISECONDS);
final CompletableFuture<Integer> combinedWithTimeout =
CompletableFutureUtils.orTimeout(combined, 1500, TimeUnit.MILLISECONDS);
System.out.println("combined result: " + combinedWithTimeout.get());
final CompletableFuture<Integer> anyOfSuccess = CompletableFutureUtils.anyOfSuccessWithType(longTaskC, longFailedTask);

final CompletableFuture<Integer> anyOfSuccess = CompletableFutureUtils.anyOfSuccess(longTaskC, longFailedTask);
System.out.println("anyOfSuccess result: " + anyOfSuccess.get());
}
}
Expand Down Expand Up @@ -263,6 +266,7 @@ fun main() {
val combined = longTaskA.thenCombine(longTaskB, Integer::sum)
.orTimeout(1500, TimeUnit.MILLISECONDS)
println("combined result: ${combined.get()}")

val anyOfSuccess: Cffu<Int> = listOf(longTaskC, longFailedTask).anyOfSuccessCffu()
println("anyOfSuccess result: ${anyOfSuccess.get()}")
}
Expand All @@ -282,19 +286,20 @@ fun main() {
示例代码如下:

```java
public class AllOfWithResultDemo {
public class AllResultsOfDemo {
public static final Executor myBizExecutor = Executors.newCachedThreadPool();
public static final CffuFactory cffuFactory = newCffuFactoryBuilder(myBizExecutor).build();

public static void main(String[] args) {
public static void main(String[] args) throws Exception {
//////////////////////////////////////////////////
// CffuFactory#allOf
// CffuFactory#allResultsOf
//////////////////////////////////////////////////
Cffu<Integer> cffu1 = cffuFactory.completedFuture(21);
Cffu<Integer> cffu2 = cffuFactory.completedFuture(42);

Cffu<Void> allOf2 = cffuFactory.allOf(cffu1, cffu2);
// Result type is Void!!
Cffu<Void> allOf = cffuFactory.allOf(cffu1, cffu2);
// Result type is Void!
//
// the result can be got by input argument `cf1.get()`, but it's cumbersome.
// so we can see a lot the util methods to enhance allOf with result in our project.

Expand All @@ -307,16 +312,16 @@ public class AllOfWithResultDemo {
CompletableFuture<Integer> cf1 = CompletableFuture.completedFuture(21);
CompletableFuture<Integer> cf2 = CompletableFuture.completedFuture(42);

CompletableFuture<Void> allOf = CompletableFuture.allOf(cf1, cf2);
// Result type is Void!!
CompletableFuture<Void> allOf2 = CompletableFuture.allOf(cf1, cf2);
// Result type is Void!

CompletableFuture<List<Integer>> allResults2 = CompletableFutureUtils.allOfWithResult(cf1, cf2);
CompletableFuture<List<Integer>> allResults2 = CompletableFutureUtils.allResultsOf(cf1, cf2);
System.out.println(allResults2.get());
}
}
```

> \# 完整可运行的Demo代码参见[`AllOfWithResultDemo.java`](cffu-core/src/test/java/io/foldright/demo/AllOfWithResultDemo.java)
> \# 完整可运行的Demo代码参见[`AllResultsOfDemo.java`](cffu-core/src/test/java/io/foldright/demo/AllResultsOfDemo.java)
上面多个相同结果类型的`CF``cffu`还提供了返回多个不同类型`CF`结果的方法,`cffuCombine`/`CompletableFutureUtils#combine`方法。

Expand All @@ -334,18 +339,18 @@ public class CffuCombineDemo {
Cffu<String> cffu1 = cffuFactory.completedFuture("21");
Cffu<Integer> cffu2 = cffuFactory.completedFuture(42);

Cffu<Tuple2<String, Integer>> allOfWithResult = cffu1.cffuCombine(cffu2);
Cffu<Tuple2<String, Integer>> combined = cffu1.cffuCombine(cffu2);
// or: cffuFactory.cffuCombine(cffu1, cffu2);
System.out.println(allOfWithResult.get());
System.out.println(combined.get());

//////////////////////////////////////////////////
// or CompletableFutureUtils.combine
//////////////////////////////////////////////////
CompletableFuture<String> cf1 = CompletableFuture.completedFuture("21");
CompletableFuture<Integer> cf2 = CompletableFuture.completedFuture(42);

CompletableFuture<Tuple2<String, Integer>> allOfWithResult2 = CompletableFutureUtils.combine(cf1, cf2);
System.out.println(allOfWithResult2.get());
CompletableFuture<Tuple2<String, Integer>> combined2 = CompletableFutureUtils.combine(cf1, cf2);
System.out.println(combined2.get());
}
}
```
Expand All @@ -367,18 +372,19 @@ public class NoDefaultExecutorSettingForCompletableFuture {
public static final Executor myBizExecutor = Executors.newCachedThreadPool();

public static void main(String[] args) {
CompletableFuture<Void> cf1 = CompletableFuture.runAsync(() -> System.out.println("doing a long time work!"),
CompletableFuture<Void> cf1 = CompletableFuture.runAsync(
() -> System.out.println("doing a long time work!"),
myBizExecutor);

CompletableFuture<Void> cf2 = CompletableFuture
.supplyAsync(
() -> {
System.out.println("doing another long time work!!");
System.out.println("doing another long time work!");
return 42;
},
myBizExecutor)
.thenAcceptAsync(
i -> System.out.println("doing third long time work!!!"),
i -> System.out.println("doing third long time work!"),
myBizExecutor);

CompletableFuture.allOf(cf1, cf2).join();
Expand All @@ -399,9 +405,9 @@ public class DefaultExecutorSettingForCffu {
Cffu<Void> cf1 = cffuFactory.runAsync(() -> System.out.println("doing a long time work!"));

Cffu<Void> cf2 = cffuFactory.supplyAsync(() -> {
System.out.println("doing another long time work!!");
System.out.println("doing another long time work!");
return 42;
}).thenAcceptAsync(i -> System.out.println("doing third long time work!!!"));
}).thenAcceptAsync(i -> System.out.println("doing third long time work!"));

cffuFactory.allOf(cf1, cf2).join();
}
Expand All @@ -414,7 +420,7 @@ public class DefaultExecutorSettingForCffu {

- `CompletableFuture``allOf`方法会等待所有输入`CF`运行完成;即使有`CF`失败了也要等待后续`CF`运行完成,再返回一个失败的`CF`
- 对于业务逻辑来说,这样失败且继续等待策略,减慢了业务响应性;会希望如果有输入`CF`失败了,则快速失败不再做于事无补的等待
- `cffu`提供了相应的`allResultsOfFastFail`/`allOfFastFail`方法
- `cffu`提供了相应的`allOfFastFail`/`allResultsOfFastFail`方法
- `allOf`/`allOfFastFail`两者都是,只有当所有的输入`CF`都成功时,才返回成功结果
- `CompletableFuture``anyOf`方法返回首个完成的`CF`(不会等待后续没有完成的`CF`,赛马模式);即使首个完成的`CF`是失败的,也会返回这个失败的`CF`结果。
- 对于业务逻辑来说,会希望赛马模式返回首个成功的`CF`结果,而不是首个完成但失败的`CF`
Expand Down Expand Up @@ -443,7 +449,7 @@ public class ConcurrencyStrategyDemo {

public static void main(String[] args) throws Exception {
////////////////////////////////////////////////////////////////////////
// CffuFactory#allResultsOfFastFail / allOfFastFail
// CffuFactory#allOfFastFail / allResultsOfFastFail
// CffuFactory#anyOfSuccess
////////////////////////////////////////////////////////////////////////
final Cffu<Integer> successAfterLongTime = cffuFactory.supplyAsync(() -> {
Expand All @@ -454,19 +460,17 @@ public class ConcurrencyStrategyDemo {

// Result type is Void!
Cffu<Void> cffuAll = cffuFactory.allOfFastFail(successAfterLongTime, failed);

Cffu<List<Integer>> fastFailed = cffuFactory.allResultsOfFastFail(successAfterLongTime, failed);
// fast failed without waiting successAfterLongTime
System.out.println(fastFailed.exceptionNow());

// Result type is Object!
Cffu<Object> cffuAny = cffuFactory.anyOfSuccess(successAfterLongTime, failed);
System.out.println(cffuAny.get());
Cffu<Integer> anyOfSuccess = cffuFactory.anyOfSuccess(successAfterLongTime, failed);
System.out.println(anyOfSuccess.get());

////////////////////////////////////////////////////////////////////////
// or CompletableFutureUtils#allOfFastFailWithResult / allOfFastFail
// CompletableFutureUtils#anyOfSuccessWithType / anyOfSuccess
// or CompletableFutureUtils#allOfFastFail / allResultsOfFastFail
// CompletableFutureUtils#anyOfSuccess
////////////////////////////////////////////////////////////////////////
final CompletableFuture<Integer> successAfterLongTimeCf = CompletableFuture.supplyAsync(() -> {
sleep(3000); // sleep LONG time
Expand All @@ -476,14 +480,12 @@ public class ConcurrencyStrategyDemo {

// Result type is Void!
CompletableFuture<Void> cfAll = CompletableFutureUtils.allOfFastFail(successAfterLongTimeCf, failedCf);
CompletableFuture<List<Integer>> fastFailedCf = CompletableFutureUtils.allOfFastFailWithResult(successAfterLongTimeCf, failedCf);

CompletableFuture<List<Integer>> fastFailedCf = CompletableFutureUtils.allResultsOfFastFail(successAfterLongTimeCf, failedCf);
// fast failed without waiting successAfterLongTime
System.out.println(CompletableFutureUtils.exceptionNow(fastFailedCf));

// Result type is Object!
CompletableFuture<Object> cfAny = CompletableFutureUtils.anyOfSuccess(successAfterLongTimeCf, failedCf);
System.out.println(cfAny.get());
CompletableFuture<Integer> cfSuccess = CompletableFutureUtils.anyOfSuccessWithType(successAfterLongTimeCf, failedCf);
CompletableFuture<Integer> cfSuccess = CompletableFutureUtils.anyOfSuccess(successAfterLongTimeCf, failedCf);
System.out.println(cfSuccess.get());
}
}
Expand Down
12 changes: 6 additions & 6 deletions cffu-core/src/main/java/io/foldright/cffu/Cffu.java
Original file line number Diff line number Diff line change
Expand Up @@ -1330,7 +1330,7 @@ public T join() {
* Waits if necessary for at most the given time for the computation to complete,
* and then retrieves its result value when complete, or throws an (unchecked) exception if completed exceptionally.
* <p>
* <b><i>NOTE:<br></i></b>
* <strong>NOTE:<br></strong>
* call this method
* <p>
* {@code result = cffu.join(timeout, unit);}
Expand All @@ -1342,7 +1342,7 @@ public T join() {
* .join();
* }</pre>
*
* <b><i>CAUTION:<br></i></b>
* <strong>CAUTION:<br></strong>
* if the wait timed out, this method throws an (unchecked) {@link CompletionException}
* with the {@link TimeoutException} as its cause;
* NOT throws a (checked) {@link TimeoutException} like {@link #get(long, TimeUnit)}.
Expand Down Expand Up @@ -1482,7 +1482,7 @@ public boolean isCancelled() {
* Returns the computation state, this method just invoke without java version compatibility logic,
* if you need this function backport into old {@code java 18-}, use {@link #cffuState()} instead.
* <p>
* <b><i>NOTE:<br></i></b>
* <strong>NOTE:<br></strong>
* {@link CompletableFuture#state} is new method since Java 19,
* this method should have compatibility logic for old Java version;
* But the return type {@link Future.State} is also added since Java 19,
Expand Down Expand Up @@ -1610,7 +1610,7 @@ public boolean cancel(boolean mayInterruptIfRunning) {
* If this CompletableFuture completes exceptionally, then the returned CompletionStage completes
* exceptionally with a CompletionException with this exception as cause.
* <p>
* <b><i>CAUTION:<br></i></b>
* <strong>CAUTION:<br></strong>
* if run on old Java 8, just return a Cffu with
* a *normal* underlying CompletableFuture which is NOT with a *minimal* CompletionStage.
* <p>
Expand Down Expand Up @@ -1839,11 +1839,11 @@ public void obtrudeException(Throwable ex) {
* Subclasses of CompletableFuture should normally override this method to return an instance of the same class
* as this CompletableFuture. The default implementation returns an instance of class CompletableFuture.
* <p>
* <b><i>NOTE:<br></i></b>
* <strong>NOTE:<br></strong>
* this method existed mainly for API compatibility to {@code CompletableFuture},
* prefer {@link CffuFactory#newIncompleteCffu()}.
* <p>
* <b><i>CAUTION:<br></i></b>
* <strong>CAUTION:<br></strong>
* for minimal stage instance({@link #isMinimalStage()}), if run on old Java 8,
* just return a Cffu with a *normal* underlying CompletableFuture which is NOT with a *minimal* CompletionStage.
*
Expand Down
6 changes: 3 additions & 3 deletions cffu-core/src/main/java/io/foldright/cffu/CffuFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public <T> Cffu<T> completedFuture(@Nullable T value) {
* Returns a new CompletionStage that is already completed with the given value
* and supports only those methods in interface {@link CompletionStage}.
* <p>
* <b><i>CAUTION:<br></i></b>
* <strong>CAUTION:<br></strong>
* if run on old Java 8, just return a Cffu with
* a *normal* underlying CompletableFuture which is NOT with a *minimal* CompletionStage.
*
Expand Down Expand Up @@ -124,7 +124,7 @@ public <T> Cffu<T> failedFuture(Throwable ex) {
* Returns a new CompletionStage that is already completed exceptionally
* with the given exception and supports only those methods in interface {@link CompletionStage}.
* <p>
* <b><i>CAUTION:<br></i></b>
* <strong>CAUTION:<br></strong>
* if run on old Java 8, just return a Cffu with
* a *normal* underlying CompletableFuture which is NOT with a *minimal* CompletionStage.
*
Expand Down Expand Up @@ -247,7 +247,7 @@ public <T> Cffu<T> newIncompleteCffu() {
* for {@link CompletableFuture} class instances,
* {@link Cffu#cffuUnwrap()} is the inverse operation to this method.
* <p>
* <b><i>NOTE</i></b>, keep input stage unchanged if possible when wrap:<br>
* <strong>NOTE</strong>, keep input stage unchanged if possible when wrap:<br>
* <ol>
* <li>if input stage is a {@link Cffu}, re-wrapped with the config of
* this {@link CffuFactory} from {@link CffuFactoryBuilder} by {@link Cffu#resetCffuFactory(CffuFactory)}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@


/**
* This class contains the enhanced methods for {@link CompletableFuture}.
* This class contains the enhanced and backport methods for {@link CompletableFuture}.
*
* @author Jerry Lee (oldratlee at gmail dot com)
*/
Expand Down Expand Up @@ -462,8 +462,8 @@ public static <T1, T2, T3, T4, T5> CompletableFuture<Tuple5<T1, T2, T3, T4, T5>>
}

////////////////////////////////////////////////////////////////////////////////
//# Backport CF methods
// compatibility for low Java version
//# Backport CF static methods
// compatibility for low Java versions
////////////////////////////////////////////////////////////////////////////////

//# Factory methods
Expand All @@ -489,7 +489,7 @@ public static <T> CompletableFuture<T> failedFuture(Throwable ex) {
* Returns a new CompletionStage that is already completed with the given value
* and supports only those methods in interface {@link CompletionStage}.
* <p>
* <b><i>CAUTION:<br></i></b>
* <strong>CAUTION:<br></strong>
* if run on old Java 8, just return a *normal* CompletableFuture which is NOT with a *minimal* CompletionStage.
*
* @param value the value
Expand All @@ -508,7 +508,7 @@ public static <T> CompletionStage<T> completedStage(@Nullable T value) {
* Returns a new CompletionStage that is already completed exceptionally with
* the given exception and supports only those methods in interface {@link CompletionStage}.
* <p>
* <b><i>CAUTION:<br></i></b>
* <strong>CAUTION:<br></strong>
* if run on old Java 8, just return a *normal* CompletableFuture which is NOT with a *minimal* CompletionStage.
*
* @param ex the exception
Expand Down Expand Up @@ -562,7 +562,7 @@ public static Executor delayedExecutor(long delay, TimeUnit unit, Executor execu
}

////////////////////////////////////////
//# backport instance methods
//# Backport CF instance methods
////////////////////////////////////////

//# Error Handling methods of CompletionStage
Expand Down Expand Up @@ -718,7 +718,7 @@ public static <T> CompletableFuture<T> exceptionallyComposeAsync(
* Waits if necessary for at most the given time for the computation to complete,
* and then retrieves its result value when complete, or throws an (unchecked) exception if completed exceptionally.
* <p>
* <b><i>NOTE:<br></i></b>
* <strong>NOTE:<br></strong>
* call this method
* <p>
* {@code result = CompletableFutureUtils.join(cf, timeout, unit);}
Expand All @@ -730,7 +730,7 @@ public static <T> CompletableFuture<T> exceptionallyComposeAsync(
* .join();
* }</pre>
*
* <b><i>CAUTION:<br></i></b>
* <strong>CAUTION:<br></strong>
* if the wait timed out, this method throws an (unchecked) {@link CompletionException}
* with the {@link TimeoutException} as its cause;
* NOT throws a (checked) {@link TimeoutException} like {@link CompletableFuture#get(long, TimeUnit)}.
Expand Down Expand Up @@ -913,7 +913,7 @@ public static <T> CompletableFuture<T> completeAsync(
* If given CompletableFuture completes exceptionally, then the returned CompletionStage completes exceptionally
* with a CompletionException with given exception as cause.
* <p>
* <b><i>CAUTION:<br></i></b>
* <strong>CAUTION:<br></strong>
* if run on old Java 8, just return a *normal* CompletableFuture which is NOT with a *minimal* CompletionStage.
*
* @return the new CompletionStage
Expand Down Expand Up @@ -963,7 +963,7 @@ public static <T, U> CompletableFuture<U> newIncompleteFuture(CompletableFuture<
* Returns the default Executor used for async methods that do not specify an Executor.
* This class uses the {@link ForkJoinPool#commonPool()} if it supports more than one parallel thread,
* or else an Executor using one thread per async task.<br>
* <b><i>CAUTION:</i></b>This executor may be not suitable for common biz use(io intensive).
* <strong>CAUTION:</strong> This executor may be not suitable for common biz use(io intensive).
*
* @return the executor
*/
Expand Down
Loading

0 comments on commit c273229

Please sign in to comment.