承诺的概念在Java

时间:2016-05-24 01:58:40

标签: java asynchronous callback

是否存在在java中使用promises的概念(就像在JavaScript中使用ut一样)而不是使用嵌套回调?

如果是这样,是否有一个关于如何在java中实现回调并且处理程序被链接的示例?

3 个答案:

答案 0 :(得分:5)

是的! Java 8将其称为CompletableFuture。它可以让你实现这样的东西。

class MyCompletableFuture<T> extends CompletableFuture<T> {

   static final Executor myExecutor = ...;

   public MyCompletableFuture() { }

   public <U> CompletableFuture<U> newIncompleteFuture() {
       return new MyCompletableFuture<U>();
   }

   public Executor defaultExecutor() {
       return myExecutor; 
   }

   public void obtrudeValue(T value) {
       throw new UnsupportedOperationException();
   }
   public void obtrudeException(Throwable ex) {
       throw new UnsupportedOperationException();
   }
}

基本设计是半流畅的API,您可以在其中安排:
  (顺序或异步)
  (功能或行动)
完成后触发    i)(“then”),或ii)(“andThen”和“orThen”)
其他。如:

MyCompletableFuture<String> f = ...; g = ...
   f.then((s -> aStringFunction(s)).thenAsync(s -> ...);
or
   f.andThen(g, (s, t) -> combineStrings).or(CompletableFuture.async(()->...)....

答案 1 :(得分:4)

更新7/20/17

我想编辑一个名为&#34; ReactFX&#34;的库。这应该是JavaFX作为反应框架。我已经看到了许多Reactive Java库,并且由于Play基于Reactive主体,我认为这些Reactive库遵循非阻塞i / o的相同原则,从服务器到客户端的异步调用通过任何一方发送通信时返回。

这些库似乎是为客户端而制作的,但也可能有服务器反应库,但我认为使用Play会更明智!与其中一个客户端反应库。

您可以查看https://www.playframework.com/

在这里实现此功能

https://www.playframework.com/documentation/2.2.0/api/java/play/libs/F.Promise.html

添加个人阅读https://www.playframework.com/documentation/2.5.x/JavaAsync

创建非阻塞操作

  

由于Play的工作方式,动作代码必须尽可能快,即无阻塞。那么,如果我们还不能计算结果,我们应该从行动中返回什么?我们应该返回结果的承诺

     

Java 8提供了一个名为CompletionStage的通用承诺 API。 CompletionStage<Result>最终将使用Result类型的值进行兑换。通过使用CompletionStage<Result>代替普通结果,我们可以快速返回操作,而不会阻止任何操作。然后,只要兑换承诺,Play就会提供结果。

     

在等待响应时将阻止Web客户端,但服务器上不会阻止任何内容,服务器资源可用于为其他客户端提供服务。

如何创建CompletionStage

  

要创建CompletionStage<Result>,我们首先需要另一个承诺承诺,它将为我们提供计算结果所需的实际值:

CompletionStage<Double> promiseOfPIValue = computePIAsynchronously();
CompletionStage<Result> promiseOfResult = promiseOfPIValue.thenApply(pi ->
                ok("PI value computed: " + pi)
);
  

播放异步​​API方法会为您提供CompletionStage。当您使用play.libs.WS API调用外部Web服务时,或者如果您使用Akka计划异步任务或使用play.libs.Akka.

与Actors通信时,就会出现这种情况      

异步执行代码块并获取CompletionStage的一种简单方法是使用CompletableFuture.supplyAsync()帮助程序:

CompletionStage<Integer> promiseOfInt = CompletableFuture.supplyAsync(() -> intensiveComputation());
  

注意:了解哪些线程代码在哪些承诺上运行非常重要。在这里,密集计算将只在另一个线程上运行。

     

通过将同步IO包装在CompletionStage中,您无法神奇地将同步IO变为异步。如果您无法更改应用程序的体系结构以避免阻塞操作,那么在某些时候必须执行操作,并且该线程将阻塞。因此,除了将操作包含在CompletionStage中之外,还必须将其配置为在单独的执行上下文中运行,该上下文已配置了足够的线程来处理预期的并发性。有关详细信息,请参阅了解播放线程池。

     

使用Actors进行阻塞操作也很有帮助。 Actors提供了一个干净的模型来处理超时和失败,设置阻塞执行上下文,以及管理可能与服务相关联的任何状态。此外,Actors提供类似ScatterGatherFirstCompletedRouter的模式来解决同时缓存和数据库请求,并允许在后端服务器集群上进行远程执行。但是,根据你的需要,演员可能会有些过分。

异步结果

  

到目前为止,我们一直在回复Result。要发送异步结果,我们的操作需要返回CompletionStage<Result>:

public CompletionStage<Result> index() {
    return CompletableFuture.supplyAsync(() -> intensiveComputation())
            .thenApply(i -> ok("Got result: " + i));
}
  

默认情况下,操作是异步的   播放操作默认是异步的。例如,在下面的控制器代码中,返回的结果内部包含在承诺中:

public Result index() {
    return ok("Got request " + request() + "!");
}
  

注意:操作代码是返回Result还是CompletionStage<Result>,两种返回的对象都以相同的方式在内部处理。有一种Action是异步的,而不是两种(同步的和异步的)。返回CompletionStage是一种编写非阻塞代码的技术。

有关CompletionStage

的一些信息

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html

这是@Debosmit Ray的答案中提到的类的子类,名为CompletableFuture

这个Youtube视频由LinkedIn开发先生Brikman解释了一些关于Promise的内容

https://youtu.be/8z3h4Uv9YbE?t=15m46s

https://www.youtube.com/watch?v=4b1XLka0UIw

我相信第一个视频给出了一个承诺的例子,第二个视频也可能提供一些好的信息,我真的不记得哪个视频有什么内容。

无论哪种方式,这里的信息都非常好,值得研究。

我个人不使用Play,但我已经看了很长很长时间了,因为它有很多非常好的东西。

答案 2 :(得分:0)

如果您甚至想在Java7之前执行Promise,则“ java-promise”可能会有用。 (当然,它适用于Java8)

您可以轻松控制异步操作​​,例如JavaScript的Promise。

https://github.com/riversun/java-promise

示例

import org.riversun.promise.Promise;
public class Example {

    public static void main(String[] args) {
        Promise.resolve("foo")
                .then(new Promise((action, data) -> {
                    new Thread(() -> {
                        String newData = data + "bar";
                        action.resolve(newData);
                    }).start();
                }))
                .then(new Promise((action, data) -> {
                    System.out.println(data);
                    action.resolve();
                }))
                .start();
        System.out.println("Promise in Java");
    }
}

结果:

Java承诺 foob​​ar