Which artist is used when compiling Java CompletedFutures?

I have a method for some repository class that returns CompletableFuture . The code that terminates these futures uses a third-party library that blocks. I intend to have a separate limited Executor that this repository class will use to make these blocking calls.

Here is an example:

 public class PersonRepository { private Executor executor = ... public CompletableFuture<Void> create(Person person) {...} public CompletableFuture<Boolean> delete(Person person) {...} } 

The rest of my application will compose these futures and do some other things with the results. When these other functions are supplied in thenAccept , thenCompose , whenComplete , etc., I do not want them to be run in Executor for the repository.

Another example:

 public CompletableFuture<?> replacePerson(Person person) { final PersonRepository repo = getPersonRepository(); return repo.delete(person) .thenAccept(existed -> { if (existed) System.out.println("Person deleted")); else System.out.println("Person did not exist")); }) .thenCompose(unused -> { System.out.println("Creating person"); return repo.create(person); }) .whenComplete((unused, ex) -> { if (ex != null) System.out.println("Creating person"); repo.close(); }); } 

The JavaDoc says:

The actions provided for dependent terminations of non-asynchronous methods can be performed by a thread that completes the current CompletableFuture or by any other caller of the termination method.

Side question: Why is there or here? In which case is there another calling completion method that does not complete the current future?

The main question: If I want all println executed by a different Executor than the other used by the repository, what methods do I need to make async and provide to the executor manually?

Obviously, thenAccept needs to be changed to thenAcceptAsync , but I'm not sure about that.

Alternative question: Which thread completes the returned future from thenCompose ?

I assume that this will be any thread that completes the future returned from the function argument. In other words, I will also need to change whenComplete to whenCompleteAsync .

I may be complicating things too much, but it seems like it can get quite complicated. I need to pay a lot of attention to where all these futures come from. Also in terms of design, if I get my future right back, how can I prevent callers from using my artist? It looks like it destroys encapsulation. I know that all conversion functions in Scala accept an implicit ExecutionContext , which seems to solve all these problems.

+5
source share
2 answers

Side question: if you assigned the intermediate variable CompletionStage variable and call the method on it, it will be executed in the same thread.

The main question: only the first, so change thenAccept to thenAcceptAsync - all of the following will take their steps in the thread that is used for adoption.

Alternative question: the thread that completed the future from thenCompose is the same one that was used for the layout.

You should think of CompletionStages as steps that are executed in quick succession in one thread (just applying the functions in order), unless you specifically want the step to be executed in another thread using async. Then, all subsequent steps are performed in this new thread.

In your current setup, the steps will be performed as follows:

 Thread-1: delete, accept, compose, complete 

The first time you take async, it becomes:

 Thread-1: delete Thread-2: accept, compose, complete 

As for your last question, about the same stream that your subscribers use, if they add additional steps - I do not think that you can do much more than return a CompletableFuture , but an ordinary Future .

+4
source

Just from my empirical observations, playing with him, the thread that performs these non-asynchronous methods will depend on what happens first, thenCompose or the task behind Future .

If thenCompose completes first (which in your case is almost certain), then the method will run in the same thread that performs the Future task.

If the task behind your Future completes first, then the method will be immediately launched in the calling thread (i.e. there is no worker at all).

+4
source

Source: https://habr.com/ru/post/1265260/


All Articles