compeletableFuture解析和响应式框架对比

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

上面介绍了 反应式编程 的一些概念。可能读者看到这里有些乱,梳理一下三者的关系:

  1. Reactive Streams 是一套反应式编程 标准规范
  2. Reactor 是基于 Reactive Streams 一套 反应式编程框架
  3. WebFluxReactor 为基础,实现 Web 领域的 反应式编程框架

https://www.cnkirito.moe/comparing-rxjava/

8 个标准,这将有助于我们理解标准特性与这些库之间的区别:

  1. Composable(可组合)
  2. Lazy(惰性执行)
  3. Reusable(可复用)
  4. Asynchronous(异步)
  5. Cacheable(可缓存)
  6. Push or Pull(推拉模型)
  7. Backpressure(回压)(译者注:按照石冲老哥的建议,这个词应当翻译成 “回压” 而不是 “背压”)
  8. Operator fusion(操作融合)

2018-04-12_20-38-07.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值