未来和承诺之间有什么区别?

use*_*330 241 java concurrency future promise

Future和之间有什么区别Promise
它们都像未来结果的占位符,但主要区别在哪里?

ass*_*ias 130

根据这个讨论,Promise最终被要求CompletableFuture包含在Java 8中,它的javadoc解释说:

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

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

f.then((s -> aStringFunction(s)).thenAsync(s -> ...);
Run Code Online (Sandbox Code Playgroud)

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

CompletableFuture<String> f = ...;
f.thenApply(this::modifyString).thenAccept(System.out::println);
Run Code Online (Sandbox Code Playgroud)

  • 这不是你的错误Assylias,但是javadoc提取物需要一位体面的技术作者进行认真的修复.在我的第五次阅读中,我可以开始欣赏它想要说的内容......而且我已经了解了已有的期货和承诺! (72认同)
  • @ Beetroot-Beetroot您应该查看特殊方法的文档.它会成为一首精彩的诗,但却是可读文档的特殊失败. (7认同)
  • 对于任何想知道的人,@ Fulluphigh指的是[这](http://gee.cs.oswego.edu/dl/jsr166/dist/docs/java/util/concurrent/CompletableFuture.html#exceptionally-java.util.function .功能-).看起来它已在Java 8中删除/大修. (4认同)
  • @ Beetroot-Beetroot似乎已经发生了. (2认同)

lba*_*scs 130

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

我认为凯文赖特的评论("你可以做出承诺,并由你来保留它.当别人让你做出承诺时,你必须等待他们是否在未来尊重它")总结得很好,但有些解释可能很有用.

期货和承诺是非常相似的概念,不同之处在于,未来是一个尚未存在的结果的只读容器,而承诺可以写入(通常只有一次).Java 8 CompletableFuture和Guava SettableFuture可以被认为是promises,因为它们的值可以设置("完成"),但它们也实现了Future接口,因此客户端没有区别.

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

另一方面,承诺的结果可以随时由"你"(或实际上由任何人)设置,因为它具有公共setter方法.CompletableFuture和SettableFuture都可以在没有任何任务的情况下创建,并且可以随时设置它们的值.您向客户端代码发送承诺,并在以后按照您的意愿完成.

请注意,CompletableFuture不是一个"纯"的承诺,它可以像FutureTask一样使用任务进行初始化,其最有用的功能是处理步骤的无关链接.

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

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

  • 我试图将差异记为管道的两端或死信箱。Promise 允许提供数据,Future 允许检索数据。我想,“承诺”通常也是“未来”也是很方便的。 (2认同)

Rah*_*thy 103

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

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

作为异步API方法的调用者,您将获得Future计算结果的句柄.您可以调用get()它来等待计算完成并检索结果.

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


Vla*_*kov 58

我将举例说明什么是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); 
Run Code Online (Sandbox Code Playgroud)

你很高兴,你要感谢你的妈妈:

Thank you mom for $10
Run Code Online (Sandbox Code Playgroud)

但是你的父亲干涉并且通常会中止妈妈的计划并完成承诺(设定其价值!)的贡献要小得多,正如父亲那样,非常坚决,而妈妈正在慢慢打开她的钱包(注意Thread.sleep(...)):

CompletableFuture<Integer> promise...
Run Code Online (Sandbox Code Playgroud)

输出是:

promise.thenAccept...
Run Code Online (Sandbox Code Playgroud)

妈妈的承诺已经创建,但等待一些"完成"事件.

promise.complete(10);
Run Code Online (Sandbox Code Playgroud)

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

// 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); 
Run Code Online (Sandbox Code Playgroud)

这时妈妈开始打开她的钱包......但很慢......

和父亲干涉得更快,完成了承诺,而不是你的妈妈:

Thank you mom for $10
Run Code Online (Sandbox Code Playgroud)

您是否注意到我明确写过的执行人?有趣的是,如果你使用默认的隐式执行器(commonPool)而父亲不在家,只有妈妈带着她的"慢钱包",那么她的承诺只会完成,如果程序的生命时间超过妈妈需要的钱钱包.我的意思是默认执行程序以"守护进程"的方式运行.我没有找到这个事实的好描述......

  • 阅读这篇文章非常有趣!我认为我不能再忘记未来和承诺了. (5认同)
  • 这必须被接受为答案。就像读故事一样。谢谢@弗拉基米尔 (3认同)

bod*_*rin 8

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

例如,看看如何在javascript中定义promises:

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);
})
Run Code Online (Sandbox Code Playgroud)

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

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);
}
Run Code Online (Sandbox Code Playgroud)

这很酷.(不像async-await那样酷,但async-await只是删除样板....然后(函数(结果){....从它).

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

new Promise( function(resolve, reject) { /* do it */ } );
Run Code Online (Sandbox Code Playgroud)

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

通过继承,如果解析拒绝是受保护的方法,则可以实现上述目的.

  • ...完全可以使用只有一个线程的`Promise`(事实上,这是他们最初设计的精确环境:javascript应用程序通常只有一个线程,因此你*不能*实现`Future "那里).因此,"Promise"比"Future"更加轻巧和高效,但是"Future"在更复杂的情况下可能会有所帮助,并且需要在线程之间进行合作,这些线程不能通过使用"Promise"来轻松排列.总结一下:"Promise"是推模型,而"Future"是拉模型(参见Iterable vs Observable) (5认同)
  • +1.这是这个问题的正确答案.`CompletableFuture`可能与'Promise`有一些相似之处但是*它仍然不是'Promise`*,因为它的意图被消费的方式不同:通过调用`then(然后)来消耗`Promise`的结果函数)`,并且在生产者调用`resolve`之后立即在生产者*的上下文中执行函数.通过调用`get`来消耗`Future`的结果,这导致消费者线程等到生产者线程生成了值,然后在消费者中处理它."未来"本质上是多线程的,但...... (4认同)

小智 5

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


yoA*_*ex5 5

未来与承诺

FuturePromise未知结果的代理对象

Promise完成一个Future

  • Promise- 未知结果的写入/生成者。
  • Future- 读取/消费者未知结果。它有以下状态:待定、已完成、已取消
//Future has a reference to Promise
Future -> Promise
Run Code Online (Sandbox Code Playgroud)

作为一个producerpromise做某事并对其负责的人

作为一个consumer检索了 a 的人,promise我希望得到一个结果future。在future我可以使用promise或拒绝它

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