371

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

Flip
  • 6,233
  • 7
  • 46
  • 75
Evgenij Reznik
  • 17,916
  • 39
  • 104
  • 181

9 Answers9

205

(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.

hc_dev
  • 8,389
  • 1
  • 26
  • 38
lbalazscs
  • 17,474
  • 7
  • 42
  • 50
  • 2
    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. – Harald Aug 06 '20 at 07:46
160

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);
assylias
  • 321,522
  • 82
  • 660
  • 783
  • 88
    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! – Beetroot-Beetroot Jan 28 '13 at 03:26
  • 2
    @Beetroot-Beetroot it seems that has happened by now. – herman Jun 03 '15 at 08:49
  • 1
    @herman Thanks - I've updated the link to point to the final version of the javadoc. – assylias Jun 03 '15 at 08:52
  • 8
    @Beetroot-Beetroot You should check out the doc for the Exceptionally method. It would make a wonderful poem, but is an exceptional failure of readable documentation. – Fulluphigh Nov 20 '15 at 19:37
  • @Fulluphigh That documentation is actually hilarious. – jamesblacklock Jun 06 '16 at 19:01
  • 4
    For anyone wondering, @Fulluphigh is referring to [this](http://gee.cs.oswego.edu/dl/jsr166/dist/docs/java/util/concurrent/CompletableFuture.html#exceptionally-java.util.function.Function-). Looks like it was removed/overhauled in Java 8. – Cedric Reichenbach Jan 03 '17 at 21:49
  • @CedricReichenbach link seems to be broken – Sniper May 25 '20 at 12:49
  • 1
    [Updated link to CompletableFuture#exceptionally](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#exceptionally-java.util.function.Function-) – Cedric Reichenbach May 25 '20 at 18:23
157

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.

Rahel Lüthy
  • 6,837
  • 3
  • 36
  • 51
  • 1
    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? – devios1 Feb 04 '18 at 17:32
  • I don't think that it is _implied_. Implementation-wise, it will often be the case though (e.g. in Java, Scala). – Rahel Lüthy Feb 05 '18 at 08:18
116

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...

Yolgie
  • 268
  • 3
  • 16
Vladimir Nabokov
  • 1,797
  • 1
  • 14
  • 19
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.

bodrin
  • 516
  • 5
  • 9
  • 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... – Periata Breatta Nov 03 '16 at 04:19
  • 6
    ...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 `Promise`s. To summarize: `Promise` is a push model, while `Future` is a pull model (cf Iterable vs Observable) – Periata Breatta Nov 03 '16 at 04:21
  • @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. – maaartinus Nov 07 '16 at 18:43
  • 1
    @maaartinus - 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](http://blog.tsunanet.net/2010/11/how-long-does-it-take-to-make-context.html). – Periata Breatta Nov 11 '16 at 04:03
  • 1
    @PeriataBreatta Actually your comment should be the accepted solution. I was looking for an explanation (pull/push, single/multi-thread) like yours. – Thomas Jacob May 06 '19 at 10:50
  • <> 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 delayed – Carmine Ingaldi Dec 07 '21 at 11:45
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.

user2562234
  • 73
  • 1
  • 5
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

yoAlex5
  • 29,217
  • 8
  • 193
  • 205
2

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

Jacky
  • 147
  • 1
  • 2
  • 7
0

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