繁体   English   中英

CompletableFuture、Future 和 RxJava 的 Observable 的区别

[英]Difference between CompletableFuture, Future and RxJava's Observable

我想知道CompletableFutureFutureObservable RxJava之间的区别。

我所知道的是都是异步的但是

Future.get()阻塞线程

CompletableFuture提供回调方法

RxJava Observable --- 类似于CompletableFuture并具有其他好处(不确定)

例如:如果客户端需要进行多个服务调用,而当我们使用Futures (Java) Future.get()将按顺序执行...想知道它在 RxJava 中如何更好..

和文档http://reactivex.io/intro.html

使用 Futures 来优化组合条件异步执行流是很困难的(或者不可能,因为每个请求的延迟在运行时会有所不同)。 这当然可以完成,但它很快变得复杂(因此容易出错)或者它过早地阻塞 Future.get(),这消除了异步执行的好处。

真的很想知道RxJava如何解决这个问题。 我发现从文档中很难理解。

期货

Futures是在 Java 5 (2004) 中引入的。 它们基本上是尚未完成的操作结果的占位符。 操作完成后, Future将包含该结果。 例如,操作可以是提交给ExecutorServiceRunnableCallable实例。 操作的提交者可以使用Future对象来检查操作是否isDone() ,或者使用阻塞的get()方法等待它完成。

例子:

/**
* A task that sleeps for a second, then returns 1
**/
public static class MyCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        Thread.sleep(1000);
        return 1;
    }

}

public static void main(String[] args) throws Exception{
    ExecutorService exec = Executors.newSingleThreadExecutor();
    Future<Integer> f = exec.submit(new MyCallable());

    System.out.println(f.isDone()); //False

    System.out.println(f.get()); //Waits until the task is done, then prints 1
}

可完成期货

CompletableFutures是在 Java 8 (2014) 中引入的。 它们实际上是常规 Futures 的演变,受到谷歌的Listenable Futures 的启发,这是Guava库的一部分。 它们是 Futures,还允许您将任务串成一个链。 你可以使用它们告诉某个工作线程“去做一些任务 X,当你完成后,使用 X 的结果去做另一件事”。 使用 CompletableFutures,您可以对操作的结果执行某些操作,而无需实际阻塞线程以等待结果。 这是一个简单的例子:

/**
* A supplier that sleeps for a second, and then returns one
**/
public static class MySupplier implements Supplier<Integer> {

    @Override
    public Integer get() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            //Do nothing
        }
        return 1;
    }
}

/**
* A (pure) function that adds one to a given Integer
**/
public static class PlusOne implements Function<Integer, Integer> {

    @Override
    public Integer apply(Integer x) {
        return x + 1;
    }
}

public static void main(String[] args) throws Exception {
    ExecutorService exec = Executors.newSingleThreadExecutor();
    CompletableFuture<Integer> f = CompletableFuture.supplyAsync(new MySupplier(), exec);
    System.out.println(f.isDone()); // False
    CompletableFuture<Integer> f2 = f.thenApply(new PlusOne());
    System.out.println(f2.get()); // Waits until the "calculation" is done, then prints 2
}

RxJava

RxJava是 Netflix 创建的用于响应式编程的完整库。 乍一看,它看起来类似于Java 8 的流 它是,除了它更强大。

与 Futures 类似,RxJava 可用于将一堆同步或异步操作串在一起以创建处理管道。 与一次性使用的 Futures 不同,RxJava 可以处理零个或多个项目的 包括具有无限数量项目的永无止境的流。 由于一组令人难以置信的丰富的运算符,它也更加灵活和强大。

与 Java 8 的流不同,RxJava 还具有 背压机制,允许它处理处理管道的不同部分在不同线程中以不同速率运行的情况

RxJava 的缺点是,尽管有可靠的文档,但由于所涉及的范式转换,它是一个具有挑战性的库。 Rx 代码也可能是调试的噩梦,尤其是在涉及多个线程的情况下,更糟糕的是 - 如果需要背压。

如果你想深入了解,官网上有一整各种教程,还有官方文档Javadoc 您还可以查看一些视频,例如这个视频,它简要介绍了 Rx,并讨论了 Rx 和 Futures 之间的区别。

奖励:Java 9 反应式流

Java 9 的 Reactive Streams aka Flow API是一组由各种反应流库(例如RxJava 2Akka StreamsVertx )实现的接口 它们允许这些反应式库相互连接,同时保留所有重要的背压。

我从 0.9 开始使用 Rx Java,现在是 1.3.2 并且很快迁移到 2.x 我在一个我已经工作了 8 年的私人项目中使用它。

如果没有这个库,我就不会再编程了。 一开始我持怀疑态度,但这是你需要创造的一种完全不同的心态。 刚开始时安静困难。 我有时会盯着弹珠看好几个小时……哈哈

这只是一个练习和真正了解流程的问题(又名可观察者和观察者的契约),一旦你到达那里,你就会讨厌这样做。

对我来说,那个库并没有真正的缺点。

用例:我有一个包含 9 个仪表(CPU、内存、网络等...)的监视器视图。 启动视图时,视图将自己订阅到一个系统监视器类,该类返回一个包含 9 米的所有数据的可观察值(间隔)。 它将每秒向视图推送一个新结果(因此不轮询!!!)。 该 observable 使用平面图同时(异步!)从 9 个不同来源获取数据,并将结果压缩到一个新模型中,您的视图将在 onNext() 上获得。

你怎么会用期货、可完成品等来做这件事……祝你好运! :)

Rx Java 为我解决了许多编程问题,并在某种程度上让我变得更容易……

好处:

  • 无国界!!! (重要的事情要提,最重要的也许是)
  • 开箱即用的线程管理
  • 构建具有自己生命周期的序列
  • 一切都是可观察的,所以链接很容易
  • 编写更少的代码
  • 类路径上的单个 jar(非常轻量级)
  • 高并发
  • 不再有回调地狱
  • 基于订阅者(消费者和生产者之间的紧密契约)
  • 背压策略(断路器之类)
  • 出色的错误处理和恢复
  • 非常好的文档(大理石 <3)
  • 完全控制
  • 还有很多 ...

缺点: - 难以测试

CompletableFuture 相对于普通 Future 的主要优势在于 CompletableFuture 利用极其强大的流 API 并为您提供回调处理程序来链接您的任务,如果您使用普通 Future,则绝对不存在。 除了提供异步架构外,CompletableFuture 是处理计算繁重的 map-reduce 任务的方法,而不必担心应用程序性能。

所有三个接口都用于将值从生产者传输到消费者。 消费者可以有两种:

  • 同步:消费者进行阻塞调用,当值准备好时返回
  • 异步:当值准备好时,调用消费者的回调方法

此外,通信接口在其他方面有所不同:

  • 能够传输多个值中的单个值
  • 如果有多个值,可以支持或不支持背压

其结果:

  • Future使用同步接口传输单个值

  • CompletableFuture使用同步和异步接口传输单个值

  • Rx使用带有背压的异步接口传输多个值

此外,所有这些通信设施都支持传输异常。 这并非总是如此。 例如, BlockingQueue没有。

Java 的Future是一个占位符,用于保存将来会通过阻塞 API 完成的内容。 您必须使用它的' isDone()方法定期轮询它以检查该任务是否已完成。 当然,您可以实现自己的异步代码来管理轮询逻辑。 但是,它会产生更多样板代码和调试开销。

Java 的CompletableFuture是由 Scala 的 Future 创新的。 它带有一个内部回调方法。 一旦完成,将触发回调方法并告诉线程应该执行下游操作。 这就是为什么它有thenApply方法来对包裹在CompletableFuture的对象做进一步的操作。

RxJava 的ObservableCompletableFuture的增强版本。 它允许您处理背压。 在我们上面提到的thenApply方法(甚至它的兄弟thenApplyAsync )中,可能会发生这种情况:下游方法想要调用有时可能变得不可用的外部服务。 在这种情况下, CompleteableFuture将完全失败,您必须自己处理错误。 但是, Observable允许您处理背压并在外部服务可用后继续执行。

此外,还有一个类似Observable接口: Flowable 它们是为不同的目的而设计的。 通常Flowable专用于处理冷和非定时操作,而Observable专用于处理需要即时响应的执行。 在这里查看官方文档: https : //github.com/ReactiveX/RxJava#backpressure

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM