compeletableFuture
AltResult
返回结果的简化
AltResult is used to box null as a result, as well as to hold exceptions.
NIL null的简化
Minor simplifications rely on (static) NIL (to
* box null results) being the only AltResult with a null
* exception field, so we don't usually need explicit comparisons.
Dependent actions
待执行的completion的stack 链
Dependent actions are represented by Completion objects linked
* as Treiber stacks headed by field "stack".
Completion
各种函数对象的包装任务,抽象了各种函数式对象操作,都有一个next属性
A Completion class with name X corresponding to function,
* prefaced with "Uni", "Bi", or "Or". Each class contains
* fields for source(s), actions, and dependent. They are
* boringly similar, differing from others only with respect to
* underlying functional forms. We do this so that users don't
* encounter layers of adaptors in common usages. We also
* include "Relay" classes/methods that don't correspond to user
* methods; they copy results from one stage to another.
x()等操作符检查completion是否被触发同时异步调度执行,如果执行完成返回true
accept()是结束符
then是操作符
Boolean CompletableFuture method x(...) (for example
* uniApply) takes all of the arguments needed to check that an
* action is triggerable, and then either runs the action or
* arranges its async execution by executing its Completion
* argument, if present. The method returns true if known to be
* complete.
tryfire调用x(),可以使用同步或者异步方式
Completion method tryFire(int mode) invokes the associated x
* method with its held arguments, and on success cleans up.
The claim() callback suppresses function
* invocation if already claimed by another thread.
xStage
调用x()时自动调用,屏蔽 X()调度执行细节,创建completion 放入到dependent actions stack中或者调用tryFire触发执行X()
CompletableFuture method xStage(...) is called from a public
* stage method of CompletableFuture x. It screens user
* arguments and invokes and/or creates the stage object. If
* not async and x is already complete, the action is run
* immediately. Otherwise a Completion c is created, pushed to
* x's stack (unless done), and started or triggered via
* c.tryFire.
get()
等待结果信号
Blocking methods get() and join() rely on Signaller Completions
* that wake up waiting threads. The mechanics are similar to
* Treiber stack wait-nodes used in FutureTask, Phaser, and
* SynchronousQueue. See their internal documentation for
* algorithmic details.
注意事项
CompletableFutures会尽快的把属性设null,因为chains会占用内存,调用方需要做null检查。
Completion属性不需要声明为final或者volatile因为是线程内部试用,是线程安全的
* Without precautions, CompletableFutures would be prone to
* garbage accumulation as chains of Completions build up, each
* pointing back to its sources. So we null out fields as soon as
* possible (see especially method Completion.detach). The
* screening checks needed anyway harmlessly ignore null arguments
* that may have been obtained during races with threads nulling
* out fields. We also try to unlink fired Completions from
* stacks that might never be popped (see method postFire).
* Completion fields need not be declared as final or volatile
* because they are only visible to other threads upon safe
* publication.
使用
public class CompletableFutureDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println(testApi());
System.out.println("testend");
}
public static Object testApi() throws ExecutionException, InterruptedException {
return CompletableFuture.completedFuture("start")
.applyToEitherAsync(CompletableFuture.completedFuture("applyToEitherAsync"), new Function<String, String>() {
@Override
public String apply(String aVoid) {
System.out.println(aVoid);
return "applyToEitherAsync.apply";
}
}).applyToEither(CompletableFuture.completedFuture("applyToEither"), new Function<String, String>() {
@Override
public String apply(String s) {
System.out.println(s);
return "applyToEither.apply";
}
}).applyToEitherAsync(CompletableFuture.completedFuture("applyToEitherAsync.ex"), new Function<String, String>() {
@Override
public String apply(String s) {
System.out.println(s);
System.out.println(Thread.currentThread());
return "applyToEitherAsync.ex.apply";
}
}, Executors.newSingleThreadExecutor())
.thenApply(new Function<String, String>() {
@Override
public String apply(String s) {
System.out.println(s);
return "thenApply.apply";
}
}).thenApplyAsync(new Function<String, String>() {
@Override
public String apply(String s) {
System.out.println(s);
return "thenApplyAsync.apply";
}
}).thenCombine(CompletableFuture.completedFuture("commbine"), new BiFunction<String, String, String>() {
@Override
public String apply(String s, String s2) {
System.out.println(s+","+s2);
return s + s2;
}
}).thenCompose(new Function<String, CompletionStage<String>>() {
@Override
public CompletionStage<String> apply(String s) {
System.out.println(s);
return CompletableFuture.completedFuture("compose" + s);
}
}).thenAccept(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
System.out.println("end");
}
}).thenRun(new Runnable() {
@Override
public void run() {
System.out.println("run");
}
}).getNow( null);
}
}
响应式对比
函数式编程的特点
- 惰性计算
- 函数是“第一等公民”
- 只使用表达式而不使用语句
- 没有副作用
迭代器和观察者
. Reactive Streams、Reactor和WebFlux
上面介绍了 反应式编程 的一些概念。可能读者看到这里有些乱,梳理一下三者的关系:
Reactive Streams
是一套反应式编程 标准 和 规范;Reactor
是基于Reactive Streams
一套 反应式编程框架;WebFlux
以Reactor
为基础,实现Web
领域的 反应式编程框架。
https://www.cnkirito.moe/comparing-rxjava/
8 个标准,这将有助于我们理解标准特性与这些库之间的区别:
- Composable(可组合)
- Lazy(惰性执行)
- Reusable(可复用)
- Asynchronous(异步)
- Cacheable(可缓存)
- Push or Pull(推拉模型)
- Backpressure(回压)(译者注:按照石冲老哥的建议,这个词应当翻译成 “回压” 而不是 “背压”)
- Operator fusion(操作融合)