ChatGPT解决这个技术问题 Extra ChatGPT

未来和承诺有什么区别?

FuturePromise 之间有什么区别?
它们都充当未来结果的占位符,但主要区别在哪里?

您可以制作 Promise,并由您自己决定是否保留它。当其他人向您做出承诺时,您必须等着看他们是否在 Future
维基百科Futures and promises
我读过的最没有帮助的维基百科文章之一

h
hc_dev

(到目前为止,我对答案并不完全满意,所以这是我的尝试......)

我认为Kevin Wright's comment

你可以做出一个承诺,并由你来遵守它。当别人给你一个承诺时,你必须等待,看看他们是否在未来兑现它

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

Futures and promises 是非常相似的概念,不同之处在于 Future 是一个只读容器,用于存储尚不存在的结果,而 Promise 可以写入(通常只能写入一次)。 Java 8 CompletableFuture 和 Guava SettableFuture 可以被认为是 Promise,因为它们的值可以设置(“完成”),但它们也实现了 Future 接口,因此对于客户端没有区别。

未来的结果将由“其他人”设置 - 由异步计算的结果。请注意 FutureTask - 一个经典的未来 - 必须 使用 Callable 或 Runnable 进行初始化,没有无参数的构造函数,并且 Future 和 FutureTask 从外部都是只读的(set 方法的 FutureTask 受到保护)。该值将设置为从内部计算的结果。

另一方面,promise 的结果可以由“你”(或者实际上任何人)随时设置,因为它有一个公共的 setter 方法。 CompletableFuture 和 SettableFuture 都可以在没有任何任务的情况下创建,并且可以随时设置它们的值。您向客户端代码发送一个承诺,并在以后如您所愿地履行它。

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

另请注意,promise 不必是 future 的子类型,也不必是同一个对象。在 Scala 中,Future 对象由异步计算或不同的 Promise 对象创建。在 C++ 中情况类似:promise 对象由生产者使用,future 对象由消费者使用。这种分离的好处是客户端无法设置未来的价值。

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


我试着记住管道两端或死信箱的区别。 Promise 允许提供数据,Future 允许检索它。我猜,Promise 通常也是 Future 也很方便。
a
assylias

根据 this discussionPromise 最终被称为 CompletableFuture 以包含在 Java 8 中,its javadoc 解释说:

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

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

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

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

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

Assylias 不是你的错,而是 javadoc 提取物需要一位体面的技术作者进行认真的修整。在我的第五次通读中,我可以开始欣赏它试图表达的意思......我理解了已经存在的未来和承诺!
@Beetroot-Beetroot 似乎现在已经发生了。
@herman 谢谢 - 我已经更新了指向 javadoc 最终版本的链接。
@Beetroot-Beetroot 您应该查看 Exceptionally 方法的文档。它会写出一首美妙的诗,但却是可读文档的异常失败。
对于任何想知道的人,@Fulluphigh 指的是 this。看起来它在 Java 8 中已被删除/大修。
R
Rahel Lüthy

我知道已经有一个可以接受的答案,但还是想加两分钱:

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

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

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


这是否意味着 Promise 始终是 Future 的子类,并且 Future 的可写性只是被类型所掩盖?
我不认为这是暗示的。在实现方面,通常会出现这种情况(例如在 Java、Scala 中)。
Y
Yolgie

我将举例说明什么是 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)而父亲不在家,而只有妈妈带着她的“慢钱包”,那么她的承诺只会完成,如果程序的寿命超过妈妈需要从钱包。

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


读这本书真是太有趣了!我不认为我可以忘记未来和承诺了。
这必须被接受为答案。就像读故事一样。谢谢@弗拉基米尔
谢谢@弗拉基米尔
高级编程语言只是为现有概念创造了新术语,我来自低级背景,多年来一直在使用 Promise 和 Future,但实际上并不知道它们是这样称呼的。
说妈咪不检查 Promise 状态,继续吃 RAM 和 CPU;我们如何检查状态和中止?
b
bodrin

不确定这是否可以成为答案,但正如我看到其他人对某人所说的那样,您可能需要对这两个概念进行两个单独的抽象,以便其中一个(Future)只是一个只读视图另一个 (Promise) ...但实际上这不是必需的。

例如看一下如何在 javascript 中定义 Promise:

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 只是删除了样板文件 ....then(function(result) {.... )。

实际上,它们的抽象作为 promise 构造函数非常好

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

允许您提供两个回调,可用于成功完成 Promise 或出错。这样只有构造 Promise 的代码才能完成它,并且接收已构造的 Promise 对象的代码具有只读视图。

如果 resolve 和 reject 是受保护的方法,则可以通过继承实现上述目标。


+1。这是这个问题的正确答案。 CompletableFuture 可能与 Promise 有一些相似之处,但它仍然不是 Promise,因为它的使用方式不同:使用 Promise 的结果通过调用 then(function),该函数在生产者调用 resolve 后立即执行在生产者的上下文中Future 的结果通过调用 get 来消耗,这导致消费者线程等待直到生产者线程生成值,然后在消费者中处理它。 Future 本质上是多线程的,但是...
...完全可以使用只有一个线程的 Promise(事实上,这正是它们最初设计的精确环境:javascript 应用程序通常只有一个线程,所以你不能 在那里实现Future)。因此,PromiseFuture更轻量级和更有效,但 Future 在更复杂的情况下很有帮助,并且需要线程之间的协作,而使用 { 1}秒。总结一下:Promise 是推送模型,而 Future 是拉取模型(参见 Iterable 与 Observable)
@PeriataBreatta 即使在单线程环境中,也必须有一些东西可以实现承诺(通常作为不同的线程运行,例如XMLHttpRequest)。我不相信效率声称,你碰巧有一些数字吗? +++ 也就是说,一个非常好的解释。
@maaartinus - 是的,某些事情必须履行承诺,但它可以(实际上在许多情况下)通过使用顶级循环来完成,该循环轮询外部状态的变化并解决与已完成操作相关的任何承诺。效率方面,我没有专门针对 Promises 的确切数据,但请注意,在未解决的 Future 上调用 get 必然涉及 2 个线程上下文切换,至少几年前可能需要 around 50 us
@PeriataBreatta 实际上,您的评论应该是公认的解决方案。我正在寻找像您这样的解释(拉/推,单/多线程)。
u
user2562234

对于客户端代码,Promise 用于在结果可用时观察或附加回调,而 Future 是等待结果然后继续。理论上任何可以用期货做的事情都可以用 Promise 做,但是由于风格的不同,不同语言的 Promise 的 API 使得链接更容易。


J
Jacky

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


y
yoAlex5

FuturePromise 是未知结果的代理对象

Promise 完成 Future

Promise - 编写/产生未知结果。

未来 - 未知结果的读取/消费者。它有下一个状态:待处理、已完成、已取消

//Future has a reference to Promise
Future -> Promise

作为producerpromise某事并为此负责

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

至于 Java CompletableFutures,它是一个 Promise,因为您可以设置结果并且它还实现了 Future


G
George Meyer

this example 中,您可以了解如何在 Java 中使用 Promises 来创建异步调用序列:

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));