2

I have read the Scala Future and Promise and this post in stackoverflow, I understand the concept is that

You can think of futures and promises as two different sides of a pipe. On the promise side, data is pushed in, and on the future side, data can be pulled out.

Right now I am wondering how to do the same thing using Java 8's CompletableFuture.

Example code:

Promise<String> promise = new Promise.DefaultPromise<>();
listOfString.stream().forEach(oneString -> {
    promise.trySuccess(oneString);
});
//..... some other computation here ....
promise.future().map(new Mapfunction{...});

I am wondering how to use Java 8 CompletableFuture to achieve the same, because I think CompletableFuture does not really have data push in and data push out concept like Scala promise does.

zt1983811
  • 1,011
  • 3
  • 14
  • 34

1 Answers1

2

In Java 8 CompletableFuture is the "write" side of the computation, whereas CompletionStage is the "read" side.

So for example:

CompletableFuture<String> fut = new CompletableFuture<String>();
listOfString.stream().forEach(oneString -> {
  fut.complete(oneString);
});
// do some stuff (possibily asynchronously)
// and then complete the future
fut.thenApply(/* some computation */);

Now, since CompletableFuture extends CompletionStage you can pass around the fut instance as a CompletionStage and your users will be able to attach async actions to perform once it complets.

Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
  • Thanks for your answer! I am still worndering how can I give ComletableFutrue a value String, then later I can use this String to do something. Like Promise can be push a String data, and later I can use Promise.futrue().map() to manipulate this String. – zt1983811 Jun 13 '17 at 13:32
  • 1
    You can use `thenApply` / `whenComplete` and similar methods defined by the `CompletionStage` interface. See https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html – Gabriele Petronella Jun 13 '17 at 13:34
  • 2
    This example can be simplified to `CompletableFuture.completedFuture("Test completable future")`… – Holger Jun 13 '17 at 14:10
  • @Holger Sorry maybe I did not explain my question very well, can you please take a look of the question again and see if we can do it with compleableFuture please? thank in advance – zt1983811 Jun 13 '17 at 14:20
  • 1
    sorry I'm not sure I follow. The idea is that you keep a reference to `fut` and complete it whenever it makes sense. At the same time you can pass it around and attach callbacks to it using `thenApply` or `whenComplete`, in the same way as you do `map` on `promise.future()`. – Gabriele Petronella Jun 13 '17 at 14:23
  • 2
    I have no experience in Scala. In the question’s example, there is `Promise.trySuccess(oneString)` in a `forEach`, which makes me wonder whether it is supposed to refer to `promise` (lowercase `p`) and what the “try in a loop” idiom means, semantically. How can this attempt fail? – Holger Jun 13 '17 at 14:27
  • But promise in scala, I can do something then come bace to promise.future(). Whereas completableFuture seems only let me do it once. I have to apply all my function at once Ex. fut.thenApply().complete(). What if I would like to seprate between thenApply() and Complete() function? I tried it but it seems like does not really work. I will put sample code in my question again for the java 8 CompletableFuture I have tried – zt1983811 Jun 13 '17 at 14:28
  • 1
    I've updated the example to match yours, but I'm sure I understand your use case. – Gabriele Petronella Jun 13 '17 at 14:36
  • 2
    @zt1983811 I’ve just read about Scala’s promise and my suspicion was right, calling `trySuccess` in a loop makes no sense. Besides that, your code doesn’t show what you have tried (with `CompletableFuture`)… – Holger Jun 13 '17 at 14:38
  • Ah yes Gabriele you are correct the answer is good, I have tried it. What I do not understand is why we can call fut.complete() before thenApply()? I will accept your answer now! – zt1983811 Jun 13 '17 at 14:42
  • 2
    @zt1983811: why not? If a `CompletableFuture` gets completed in an asynchronous operation, you also have no control over whether the completion will be “before” the `thenApply` or not, as that’s what concurrency is about. I’m quiet sure that Scala’s promise/future feature supports this the same way… – Holger Jun 13 '17 at 14:44
  • @Holger well trySuccess is just a way to push the data to promise once it finished then get the future and do something else. Gabriele has answer the question correctly I htink – zt1983811 Jun 13 '17 at 14:44
  • 2
    @zt1983811: what do you mean with “once it finished”? The `trySuccess` *is* finishing it and that will happen with the *first* element. So it doesn’t make any sense to repeat that operation for *all* elements of the list, as all but the first attempt will be ignored. – Holger Jun 13 '17 at 14:46
  • @Holger So basiclly java 8 completableFuture.complete() == scala promise.tryScuess()? I do think so becasue scala has tryComplete, trySuccess and tryFailure also scala has Complete, Success and Failure. I think in java 8 make I have to do some interfunction in complete() method to achieve the same in scala – zt1983811 Jun 13 '17 at 14:48
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/146544/discussion-between-zt1983811-and-holger). – zt1983811 Jun 13 '17 at 14:50