Java CompletableFuture get Method - java

I am having some trouble understanding CompletableFuture. I do not understand the get() method. Please correct me if I am wrong, but it says
"Waits if necessary for this future to complete, and then returns its result." So If I do not return any result I do not have to call get method?
Please see below. Even I do not call get() method it still does its job. So I understand get() as if the future returns something it will make sense then, otherwise get() is not necessary for a future that does not return anything.
//Since it does not return something two statements below do the same thing.
CompletableFuture.runAsync(doSomething());
CompletableFuture.runAsync(doSomething()).get();
private final CompletableFuture<Void> doSomething() {
//do something
return null;
}

The main purpose of get() is to wait for the task to complete, then return the result.
If your task is a Runnable, not Callable, it will return a Void, so as you have pointed out, there is no point in checking the result. For such tasks you are executing get() only to wait for them to complete.
The main advantages of CompletableFuture are the methods that allow you to handle exceptions, and further process the data. It also has methods wo wait for all and single task to complete from a set of ComplatableFuture tasks. So it's mutch easyer to work in multithread anv. get() method works same as for Future class though.
UPDATE:
If you don't require for them to complete before passing further in your application, you don't have to call get() method at all. But it would be wise to keep a reference to them, and wait for them to complete or cancel them before exiting a program. At some point of the program you probably will want to see if they have completed.
But if you want for the to complete before going further, then you can use CompletableFuture.allOf().
In some cases it's also wise to add a timeout to their execution, so that you will not have a hanging thread in your application. This may be dangerous, especially on mobile environment.
So it all depends on your business case.

Related

Is nesting of futures an anti pattern?

I have a ListenableFuture that I am creating like:
ListenableFuture<X> future1 = ...
ListenableFuture<X> future2 = ...
Futures.addCallback(future1, futureCallback, executor);
Now inside the futureCallback I do :
public void onSuccess(Object result) {
Object f2 = future2.get();
.
.
. <do something with f2>
}
Is it a bad thing to do a .get() call in a callback? I was told that I could get into a hung up state. Is that true and why would it so happen?
What is the alternative of achieving the same thing in a better way?
You probably want something more like:
whenAllSucceed(future1, future2).run(...)
The Runnable you pass to run will still have to call future2.get. Still, whenAllComplete has some advantages over the addCallback approach:
The addCallback approach may require a thread to block on future2.get until future2 is done. (This is at least a small waste of resources. If you run out of threads, your code may hang. Or you might try to create a new thread and run out of memory.) With whenAllComplete, your Runnable won't run until both input futures are done, so future2.get will not block.
whenAllComplete returns a Future. You can use this to check for errors. And if you cancel it, it will cancel both input futures.
Note also that whenAllSucceed will log if multiple inputs fail. This isn't always desirable. If you don't want the logging, you might prefer whenAllComplete. (Hopefully someday we will provide a way to turn off the logging.)
Doing a .get() call in a callback is outright usual -- it's what you want to do most of the time -- but a more standard pattern is to, instead, use transform or transformAsync to pass in a function that takes the result directly.
Doing blocking operation in callback (e.g. future.get) destroys the idea of asynchronous programming, turning asynchronous program in ordinary multithreaded. So this is indeed an antipattern.
It's OK, however, to call get() if you are sure it would not block.
If you want a callback which waits for 2 asynchronous results, you can use CompletableFuture instead:
CompletableFuture<X> future1 = ...
CompletableFuture<X> future2 = ...
CompletableFuture future3 = future1.thenCombineAsync(future 2, futureCallback, executor);

Advice for an asynchronous programming problem in Java

I have a set of classes which encapsulate a unit of work on Google Sheets. After the class's execute method is called, they pass a request to a service, bundled with a callback which the service should call on task completion. (As the tasks are non-critical and repeated frequently, the service just logs errors and does not call the class back if its request fails).
Stripped down, the tasks look like this:
public void execute() {
//preparatory stuff, then...
Request r = new Request(this::callback);
service.execute(r);
}
public void callback(Result result) {
...
}
The call to the service is synchronous but within the service, the Request is queued, executed asynchronously, and the callback is invoked on a new thread. Some of the tasks involve several service invocations, the callback methods may themselves create a Request with a second callback method and invoke the service again. I want that to be invisible to client code.
My problem now is that I would like to run the tasks asynchronously from client code and then execute an arbitrary handler after they are done. One way to do this would be to give the class a callback in the execute() method for it to call once execution is complete. But I'd really rather be able to do this inline in code, this sort of thing:
CompletableFuture.supplyAsync(() -> (new Task()).execute()).whenComplete((result, error) -> {});
The problem with that is, the completion of the execute() method does not signal the end of the task, as the task is still awaiting its callback. The other thing is, that callback might never arrive. I can't figure out how I should go about calling the task such that I can run it asynchronously and inline like in the code above and the whenComplete() will be invoked when the Task class explicitly decides it is finished. I'd also need a timeout, as the tasks's callback may not be invoked.
Any ideas? Note that I control the service invoked by the tasks, so I can change how that works if necessary, but I'd probably rather not.
I'd spend some time looking around in java.util.concurrent. Can't you just use an ExecutorService for a lot of this? You can submit() Callable code and get a future back, you can submit a list of Callables and give a timeout, you can call shutdown() and then awaitTermination() to wait for the processing to stop. You can get these notification callbacks by just submitting a Callable that constructs with the callback interface and invokes it when it feelsl like it's done.
Failing this, you might look at actors. Your concurrency pattern would likely be very easy in the actor model.
Going to answer my own question here: I just altered the task execute methods to return a CompletableFuture<TaskResult> with TaskResult containing the desired information. The task stores the CompletableFuture internally and calls complete() as needed in later callbacks. Not sure why I had trouble seeing this solution.

Which executor is used when composing Java CompletableFutures?

I have a method on some repository class that returns a CompletableFuture. The code that completes these futures uses a third party library which blocks. I intend to have a separate bounded Executor which 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 that are supplied to thenAccept, thenCompose, whenComplete, etc, I don't want them to run on the 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 states:
Actions supplied for dependent completions of non-async methods may be performed by the thread that completes the current CompletableFuture, or by any other caller of a completion method.
Side question: Why is there an or here? In what case is there another caller of a completion method that does not complete the current future?
Main question: If I want all the println to be executed by a different Executor than the one used by the repository, which methods do I need to make async and provide the executor manually?
Obviously the thenAccept needs to be changed to thenAcceptAsync but I'm not sure about that point onwards.
Alternative question: Which thread completes the returned future from thenCompose?
My guess is that it will be whatever thread completes the future returned from the function argument. In other words I would need to also change whenComplete to whenCompleteAsync.
Perhaps I am over complicating things but this feels like it could get quite tricky. I need to pay a lot of attention to where all these futures come from. Also from a design point of view, if I return a future, how do I prevent callers from using my executor? It feels like it breaks encapsulation. I know that all the transformation functions in Scala take an implicit ExecutionContext which seems to solve all these problems.
Side Question: If you assigned the intermediate CompletionStage to a variable and call a method on it, it would get executed on the same thread.
Main Question: Only the first one, so change thenAccept to thenAcceptAsync -- all the following ones will execute their steps on the thread that is used for the accept.
Alternative Question: the thread that completed the future from thenCompose is the same one as was used for the compose.
You should think of the CompletionStages as steps, that are executed in rapid succession on the same thread (by just applying the functions in order), unless you specifically want the step to be executed on a different thread, using async. All next steps are done on that new thread then.
In your current setup the steps would be executed like this:
Thread-1: delete, accept, compose, complete
With the first accept async, it becomes:
Thread-1: delete
Thread-2: accept, compose, complete
As for your last question, about the same thread being used by your callers if they add additional steps -- I don't think there is much you can do about aside from not returning a CompletableFuture, but a normal Future.
Just from my empirical observations while playing around with it, the thread that executes these non-async methods will depend on which happens first, thenCompose itself or the task behind the Future.
If thenCompose completes first (which, in your case, is almost certain), then the method will run on the same thread that is executing the Future task.
If the task behind your Future completes first, then the method will run immediately on the calling thread (i.e. no executor at all).

Non-cancellable futures returned by a thread-pool. Do they exist?

I'm currently implementing a service that works in a concurrent setting and that has as operations a bunch of blocking methods.
I would like to change that so they return a Future<?> instead and it's up to the client to decide whether he wants to execute get() and block the thread or not. The problem is that Future<?> brings baggage, ie, it is possible to invoke cancellation on a future. But if that were to actually happen then it would most probably break my service's invariants.
Is there any easy way to make a thread-pool return non-cancellable futures? Currently, the only solution I'm seeing is wrapping the thread-pool future's into a future of mine that will throw an UnsupportedException if some attempts to cancel the operation. Or just return an object of my own, but I'd like to KISS if possible.
I think, you fear too much. I see two VERY simple solutions:
decorate (wrap) the default FutureTask and override in your ExecutorService the newTaskFor() method returning your new class.
do nothing, i.e do not cancel any work in your Callables or Runnables. In order to make your life easier you could take a look at Guava's uninterruptibles.

Should I call cancel(true) on Future<?> or my own FutureTask

I have a custom class MyFutureTask extends FutureTask<Void> upon which I do some code on the done() method.
I use an ExecutorService which I call submit(new MyFutureTask()) into it.
Now I can keep a reference to the Future<?> that gets returned after you call submit, but when I call cancel to that the isCancelled() method never returns true.
Should I ignore the Future<?> object that gets returned and instead work with MyFutureTask and call cancel(true) on that instead?
What is the use of the Future<?> object then?
edit: What's the difference between Future and FutureTask in Java? from this thread I understand the difference.
Besides the default cancel behavior I also want to attempt to stop a network call in progress so I guess the route I am going to use FutureTask is correct. Someone can confirm?
Don't use Executor.submit, instead use Executor.execute since you already have a Future. When you call submit, you are just needlessly wrapping your FutureTask in another FutureTask.
Also you can't "stop" a network trip. You have to wait until it returns or times out. What you do is call Future.cancel(true), then when your network trip returns look and see if the future has been canceled Future.isCancelled(). THen you can just stop doing what you were doing in the Future. For all intents and purposes it's the same effect as if you could cancel a network trip. To the end user (ie the client code or caller) it will appear the same way. The only side effect you might notice is if you have only a single thread executing tasks in which case the thread waiting on the network trip has to return before it will pick up the next task. If that's a problem using a pool of threads.
As an aside if you used NIO or some library thereof you could stop waiting on the result immediately, but that's a lot more work to code up.

Categories

Resources