What's the difference between a Future and a Promise?
Asked Answered
E

9

383

What's the difference between Future and Promise?
They both act like a placeholder for future results, but where is the main difference?

Extraterrestrial answered 26/1, 2013 at 21:56 Comment(4)
You can make a Promise and it's up to you to keep it. When someone else makes you a promise you must wait to see if they honour it in the FutureTriptych
wikipedia Futures and promisesHowlett
One of the least helpful Wikipedia articles I've ever readInfluent
dist-prog-book.com/chapter/2/futures.htmlGreenebaum
A
162

According to this discussion, Promise has finally been called CompletableFuture for inclusion in Java 8, and its javadoc explains:

A Future that may be explicitly completed (setting its value and status), and may be used as a CompletionStage, supporting dependent functions and actions that trigger upon its completion.

An example is also given on the list:

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

Note that the final API is slightly different but allows similar asynchronous execution:

CompletableFuture<String> f = ...;
f.thenApply(this::modifyString).thenAccept(System.out::println);
Aphrodisia answered 26/1, 2013 at 22:7 Comment(8)
It's not your fault Assylias, but that javadoc extract needs a serious workover by a decent tech author. On my fifth read-through I can just start to appreciate what it's trying to say ... and I come to this with an understanding of futures and promises already in place!Package
@Package it seems that has happened by now.Feat
@Feat Thanks - I've updated the link to point to the final version of the javadoc.Aphrodisia
@Package You should check out the doc for the Exceptionally method. It would make a wonderful poem, but is an exceptional failure of readable documentation.Influent
@Influent That documentation is actually hilarious.Incubate
For anyone wondering, @Influent is referring to this. Looks like it was removed/overhauled in Java 8.Folderol
@CedricReichenbach link seems to be brokenWhomsoever
Updated link to CompletableFuture#exceptionallyFolderol
H
211

(I'm not completely happy with the answers so far, so here is my attempt...)

I think that Kevin Wright's comment

You can make a Promise and it's up to you to keep it. When someone else makes you a promise you must wait to see if they honour it in the Future

summarizes it pretty well, but some explanation can be useful.

Futures and promises are pretty similar concepts, the difference is that a future is a read-only container for a result that does not yet exist, while a promise can be written (normally only once). The Java 8 CompletableFuture and the Guava SettableFuture can be thought of as promises, because their value can be set ("completed"), but they also implement the Future interface, therefore there is no difference for the client.

The result of the future will be set by "someone else" - by the result of an asynchronous computation. Note how FutureTask - a classic future - must be initialized with a Callable or Runnable, there is no no-argument constructor, and both Future and FutureTask are read-only from the outside (the set methods of FutureTask are protected). The value will be set to the result of the computation from the inside.

On the other hand, the result of a promise can be set by "you" (or in fact by anybody) anytime because it has a public setter method. Both CompletableFuture and SettableFuture can be created without any task, and their value can be set at any time. You send a promise to the client code, and fulfill it later as you wish.

Note that CompletableFuture is not a "pure" promise, it can be initialized with a task just like FutureTask, and its most useful feature is the unrelated chaining of processing steps.

Also note that a promise does not have to be a subtype of future and it does not have to be the same object. In Scala a Future object is created by an asynchronous computation or by a different Promise object. In C++ the situation is similar: the promise object is used by the producer and the future object by the consumer. The advantage of this separation is that the client cannot set the value of the future.

Both Spring and EJB 3.1 have an AsyncResult class, which is similar to the Scala/C++ promises. AsyncResult does implement Future but this is not the real future: asynchronous methods in Spring/EJB return a different, read-only Future object through some background magic, and this second "real" future can be used by the client to access the result.

Heteronomy answered 2/3, 2015 at 23:1 Comment(1)
I try to remember the difference as two ends of a pipe or a dead letter box. Promise allows to provide data, Future allows to retrieve it. That a Promise is often a Future too is convenience, I guess.Verbalize
A
162

According to this discussion, Promise has finally been called CompletableFuture for inclusion in Java 8, and its javadoc explains:

A Future that may be explicitly completed (setting its value and status), and may be used as a CompletionStage, supporting dependent functions and actions that trigger upon its completion.

An example is also given on the list:

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

Note that the final API is slightly different but allows similar asynchronous execution:

CompletableFuture<String> f = ...;
f.thenApply(this::modifyString).thenAccept(System.out::println);
Aphrodisia answered 26/1, 2013 at 22:7 Comment(8)
It's not your fault Assylias, but that javadoc extract needs a serious workover by a decent tech author. On my fifth read-through I can just start to appreciate what it's trying to say ... and I come to this with an understanding of futures and promises already in place!Package
@Package it seems that has happened by now.Feat
@Feat Thanks - I've updated the link to point to the final version of the javadoc.Aphrodisia
@Package You should check out the doc for the Exceptionally method. It would make a wonderful poem, but is an exceptional failure of readable documentation.Influent
@Influent That documentation is actually hilarious.Incubate
For anyone wondering, @Influent is referring to this. Looks like it was removed/overhauled in Java 8.Folderol
@CedricReichenbach link seems to be brokenWhomsoever
Updated link to CompletableFuture#exceptionallyFolderol
O
161

I am aware that there's already an accepted answer but would like to add my two cents nevertheless:

TLDR: Future and Promise are the two sides of an asynchronous operation: consumer/caller vs. producer/implementor.

As a caller of an asynchronous API method, you will get a Future as a handle to the computation's result. You can e.g. call get() on it to wait for the computation to complete and retrieve the result.

Now think of how this API method is actually implemented: The implementor must return a Future immediately. They are responsible for completing that future as soon as the computation is done (which they will know because it is implementing the dispatch logic ;-)). They will use a Promise/CompletableFuture to do just that: Construct and return the CompletableFuture immediately, and call complete(T result) once the computation is done.

Ommiad answered 6/1, 2015 at 7:17 Comment(2)
Does this imply that a Promise is always a subclass of Future, and that the writeability of the Future is just obscured by the type?Malaco
I don't think that it is implied. Implementation-wise, it will often be the case though (e.g. in Java, Scala).Tibold
K
123

I will give an example of what is Promise and how its value could be set at any time, in opposite to Future, which value is only readable.

Suppose you have a mom and you ask her for money.

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

Output of that is:

Thank you mom for $10

Mom's promise was created , but waited for some "completion" event.

CompletableFuture<Integer> promise...

You created such event, accepting her promise and announcing your plans to thank your mom:

promise.thenAccept...

At this moment mom started open her purse...but very slow...

and father interfered much faster and completed the promise instead of your mom:

promise.complete(10);

Have you noticed an executor that I wrote explicitly?

Interestingly, if you use a default implicit executor instead (commonPool) and father is not at home, but only mom with her "slow purse", then her promise will only complete, if the program lives longer than mom needs to get money from the purse.

The default executor acts kind of like a "daemon" and does not wait for all promises to be fulfilled. I have not found a good description of this fact...

Knapp answered 1/2, 2017 at 5:55 Comment(5)
It's so much fun to read this one! I don't think I could forget future and promise anymore.Makeweight
This must be accepted as the answer. Its just like reading a story. Thanks @VladimirDevonadevondra
Thanks @VladimirCleaner
High-level programming languages just have coined new terms for existing concepts, I come from a low-level background and have been using promise and future for years without actually knowing they are called so.Yelena
Said Mom does not check Promise status, and continues to eat RAM and CPU; How can we check status and abort?Hofmann
P
10

Not sure if this can be an answer but as I see what others have said for someone it may look like you need two separate abstractions for both of these concepts so that one of them (Future) is just a read-only view of the other (Promise) ... but actually this is not needed.

For example take a look at how promises are defined in javascript:

https://promisesaplus.com/

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

The focus is on the composability using the then method like:

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

which makes asynchronous computation to look like synchronous:

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

which is pretty cool. (Not as cool as async-await but async-await just removes the boilerplate ....then(function(result) {.... from it).

And actually their abstraction is pretty good as the promise constructor

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

allows you to provide two callbacks which can be used to either complete the Promise successfully or with an error. So that only the code that constructs the Promise can complete it and the code that receives an already constructed Promise object has the read-only view.

With inheritance the above can be achieved if resolve and reject are protected methods.

Photovoltaic answered 27/5, 2016 at 7:37 Comment(6)
+1. This is the correct answer to this question. CompletableFuture might have some similarity to a Promise but it still isn't a Promise, because the way it's intended to be consumed is different: a Promise's result is consumed by calling then(function), and the function is executed in the context of the producer immediately after the producer calls resolve. A Future's result is consumed by calling get which causes the consumer thread to wait until the producer thread has generated the value, then processes it in the consumer. Future is inherently multithreaded, but...Peppergrass
...it is entirely possible to use a Promise with only a single thread (and in fact that is the precise environment they were originally designed for: javascript applications generally only have a single thread, so you cannot implement Future there). Promise is therefore much more lightweight and efficient than Future, but Future can be helpful in situations that are more complex and require cooperation between threads that can't easily be arranged by using Promises. To summarize: Promise is a push model, while Future is a pull model (cf Iterable vs Observable)Peppergrass
@PeriataBreatta Even in a single-threaded environment, there must be something fulfilling the promise (which typically sort of runs as a different thread, e.g., an XMLHttpRequest). I don't believe the efficiency claim, do you happen to have some figures? +++ That said, a very nice explanation.Doubleteam
@Doubleteam - yes, something must fulfil the promise, but it can (and in fact in many cases is) done by using a top level loop that polls for changes in external state and resolves whichever promises relate to actions that have finished. Efficiency wise, I have no firm figures for Promises specifically, but note that calling get on an unresolved Future will necessarily involve 2 thread context switches, which at least a few years back was likely to require around 50 us.Peppergrass
@PeriataBreatta Actually your comment should be the accepted solution. I was looking for an explanation (pull/push, single/multi-thread) like yours.Instance
<<Not as cool as async-await but async-await just removes the boilerplate>> this construct is not just syntactic sugar: async/await makes promises work like future, as it blocks the computation until the promise is fulfilled/rejected. with .then() you can still execute the remaining code in your function immediately, with async/await, all the subsequent instructions will be delayedTybi
S
6

For client code, Promise is for observing or attaching callback when a result is available, whereas Future is to wait for result and then continue. Theoretically anything which is possible to do with futures what can done with promises, but due to the style difference, the resultant API for promises in different languages make chaining easier.

Stereophonic answered 25/11, 2017 at 18:10 Comment(0)
F
5

Future vs Promise

Future and Promise are proxy object for unknown result

Promise completes a Future

  • Promise - write/producer of unknown result.
  • Future - read/consumer of unknown result. It has next states: pending, fulfilled, canceled
//Future has a reference to Promise
Future -> Promise

As a producer I promise something and responsible for it

As a consumer who retrieved a promise I expect to have a result in future. In future I can use the promise or reject it

As for Java CompletableFutures it is a Promise because you can set the result and also it implements Future

Felon answered 6/2, 2021 at 21:58 Comment(1)
Your comment made things clearer for me. So I guess developers could have called a Future an Expectation (to be the perfect counterpart for Promise), but as Expect is already used for error handling, that would have confused everybody I guess :DMillian
P
2

No set method in Future interface, only get method, so it is read-only. About CompletableFuture, this article maybe helpful. completablefuture

Pelagia answered 6/9, 2017 at 17:33 Comment(0)
S
1

In this example you can take a look at how Promises can be used in Java for creating asynchronous sequences of calls:

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));
Sailplane answered 2/7, 2020 at 12:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.