未来和承诺的区别是什么?

FuturePromise有什么区别?< br > 它们都像未来结果的占位符,但主要的区别在哪里?< / p >
202649 次浏览

根据这个讨论,为了包含在Java 8中,Promise最终被称为CompletableFuture,并且它的javadoc解释了:

一个可以显式完成的Future(设置其值和状态),并且可以用作CompletionStage,支持在其完成时触发的依赖函数和操作。

列表中还给出了一个例子:

f.then((s -> aStringFunction(s)).thenAsync(s -> ...);

注意,最终的API略有不同,但允许类似的异步执行:

CompletableFuture<String> f = ...;
f.thenApply(this::modifyString).thenAccept(System.out::println);

我知道已经有了一个公认的答案,但我仍然想补充我的意见:

Future和Promise是异步操作的两个方面:消费者/调用者 vs. 生产商/实现者

作为异步API方法的调用者,你将得到一个Future作为计算结果的句柄。例如,你可以在它上调用get()来等待计算完成并检索结果。

现在想想这个API方法实际上是如何实现的:实现者必须立即返回Future。它们负责在计算完成后立即完成该future(它们将知道这一点,因为它正在实现分派逻辑;-))。它们将使用Promise/CompletableFuture来完成这一点:立即构造并返回CompletableFuture,并在计算完成后调用complete(T result)

(到目前为止,我对答案不是很满意,所以这里是我的尝试…)

我认为凯文·赖特的评论

你可以做出一个承诺,它是由你来遵守它。当别人向你许下承诺时,你必须等着看他们将来是否遵守

总结得很好,但一些解释可能是有用的。

未来与承诺是非常相似的概念,不同的是future是一个还不存在的结果的只读容器,而promise可以被写入(通常只有一次)。Java 8 CompletableFuture和Guava SettableFuture可以被认为是承诺,因为它们的值可以设置(“完成”),但它们也实现了Future接口,因此对客户端没有区别。

未来的结果将由“别人”决定。-由异步计算的结果。注意FutureTask -经典的future - 必须是如何用Callable或Runnable初始化的,没有无参数构造函数,而且future和FutureTask从外部看都是只读的(FutureTask的set方法是受保护的)。该值将从内部设置为计算的结果。

另一方面,承诺的结果可以由“你”来设定。(实际上是任何人)因为它有一个公共setter方法。CompletableFuture和SettableFuture都可以在没有任何任务的情况下创建,它们的值可以在任何时候设置。您向客户端代码发送一个承诺,并在稍后按照您的意愿实现它。

请注意,CompletableFuture不是一个“纯粹的”;它可以像FutureTask一样用任务初始化,它最有用的特性是处理步骤的不相关链接。

还要注意,promise不一定是future的子类型,也不一定是同一个对象。在Scala中,Future对象是由异步计算或不同的 Promise对象创建的。在c++中,情况类似:承诺对象由生产者使用,而未来对象由消费者使用。这种分离的好处是客户端不能设置将来的值。

春天EJB 3.1都有一个AsyncResult类,这类似于Scala/ c++的承诺。AsyncResult确实实现了Future,但这不是真正的未来:Spring/EJB中的异步方法通过一些后台魔法返回一个不同的只读Future对象,而这个第二个“real"客户端可以使用Future来访问结果。

不确定这是否可以成为一个答案,但正如我看到其他人对某人说的那样,看起来你需要两个不同的抽象这两个概念,以便其中一个(Future)只是另一个(Promise)的只读视图…但实际上这是不需要的。

例如,看看在javascript中承诺是如何定义的:

https://promisesaplus.com/

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

重点是使用then方法的可组合性,如:

asyncOp1()
.then(function(op1Result){
// do something
return asyncOp2();
})
.then(function(op2Result){
// do something more
return asyncOp3();
})
.then(function(op3Result){
// do something even more
return syncOp4(op3Result);
})
...
.then(function(result){
console.log(result);
})
.catch(function(error){
console.log(error);
})

这使得异步计算看起来像同步:

try {
op1Result = syncOp1();
// do something
op1Result = syncOp2();
// do something more
op3Result = syncOp3();
// do something even more
syncOp4(op3Result);
...
console.log(result);
} catch(error) {
console.log(error);
}

,这很酷。 (不像async-await那么酷,但async-await只是从它中删除了样板文件然后(函数(结果){…)

实际上它们的抽象作为承诺构造函数很好

new Promise( function(resolve, reject) { /* do it */ } );

允许你提供两个回调,它们可以用来成功地完成Promise,也可以被用来报错。因此,只有构造Promise的代码才能完成它,而接收已经构造的Promise对象的代码具有只读视图。

通过继承,如果解决拒绝是受保护的方法,就可以实现上述目标。

我将给出一个例子,说明什么是Promise,以及如何在任何时候设置它的值,与之相反的是Future,后者的值只能读。

假设你有一个妈妈,你向她要钱。

// Now , you trick your mom into creating you a promise of eventual
// donation, she gives you that promise object, but she is not really
// in rush to fulfill it yet:
Supplier<Integer> momsPurse = ()-> {


try {
Thread.sleep(1000);//mom is busy
} catch (InterruptedException e) {
;
}


return 100;


};




ExecutorService ex = Executors.newFixedThreadPool(10);


CompletableFuture<Integer> promise =
CompletableFuture.supplyAsync(momsPurse, ex);


// You are happy, you run to thank you your mom:
promise.thenAccept(u->System.out.println("Thank you mom for $" + u ));


// But your father interferes and generally aborts mom's plans and
// completes the promise (sets its value!) with far lesser contribution,
// as fathers do, very resolutely, while mom is slowly opening her purse
// (remember the Thread.sleep(...)) :
promise.complete(10);

它的输出是:

Thank you mom for $10

妈妈的承诺被创造出来了,但等待着一些“完成”的事件。

CompletableFuture<Integer> promise...

你创造了这样一个活动,接受她的承诺,并宣布你的计划来感谢你的妈妈:

promise.thenAccept...

就在这时,妈妈开始打开她的钱包……但是非常慢……

父亲比你妈妈更快地完成了承诺:

promise.complete(10);

你注意到我明确写的一个执行者了吗?

有趣的是,如果您使用默认的隐式执行器(commonPool),并且父亲不在家,而只有母亲带着她的“慢钱包”,那么她的承诺只有在程序存活的时间比母亲从钱包中获取资金所需的时间长时才会完成。

默认执行程序的行为有点像“守护进程”,并不等待所有的承诺被履行。我还没有找到一个很好的描述这个事实的词……

Future接口没有set方法,只有get方法,所以是只读的。 关于CompletableFuture,这篇文章可能会有帮助。 completablefuture < / p >

对于客户端代码,Promise用于在结果可用时观察或附加回调,而Future用于等待结果然后继续。从理论上讲,任何可以用未来完成的事情都可以用承诺完成,但由于风格的差异,不同语言的承诺的最终API使得链接更容易。

这个例子中,你可以看看如何在Java中使用promise 用于创建异步调用序列:

doSomeProcess()
.whenResult(result -> System.out.println(String.format("Result of some process is '%s'", result)))
.whenException(e -> System.out.println(String.format("Exception after some process is '%s'", e.getMessage())))
.map(String::toLowerCase)
.mapEx((result, e) -> e == null ? String.format("The mapped result is '%s'", result) : e.getMessage())
.whenResult(s -> System.out.println(s));

未来vs承诺

FuturePromise是未知结果的代理对象

Promise完成Future

  • Promise -未知结果的写入/生成。
  • Future -读取/消费者未知的结果。它有接下来的状态:待处理、完成、取消
//Future has a reference to Promise
Future -> Promise

作为一个producer,我promise一些东西,并对它负责

作为检索promiseconsumer,我希望在future中有一个结果。在future中,我可以使用promise或拒绝它

对于Java CompletableFutures,它是Promise,因为你可以设置结果,而且它实现了Future