是否存在在java中使用promises的概念(就像在JavaScript中使用ut一样)而不是使用嵌套回调?
如果是这样,是否有一个关于如何在java中实现回调并且处理程序被链接的示例?
答案 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<Result>
,我们首先需要另一个承诺:承诺,它将为我们提供计算结果所需的实际值:
CompletionStage<Double> promiseOfPIValue = computePIAsynchronously();
CompletionStage<Result> promiseOfResult = promiseOfPIValue.thenApply(pi ->
ok("PI value computed: " + pi)
);
播放异步API方法会为您提供
与Actors通信时,就会出现这种情况CompletionStage
。当您使用play.libs.WS
API调用外部Web服务时,或者如果您使用Akka计划异步任务或使用play.libs.Akka.
异步执行代码块并获取
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承诺 foobar