I encountered a strange situation. I'm fiddling with CompletableFuture and when running the following code I have unexpected results:
public static void main(String[] args) {
CompletableFuture<CompletableFuture<CompletableFuture<CompletableFuture<CompletableFuture<CompletableFuture<Object>>>>>> completableFutureCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("first");
return CompletableFuture.supplyAsync(() -> {
System.out.println("second");
return CompletableFuture.supplyAsync(() -> {
System.out.println("third");
return CompletableFuture.supplyAsync(() -> {
System.out.println("fourth");
return CompletableFuture.supplyAsync(() -> {
System.out.println("fifth");
return CompletableFuture.completedFuture(null);
});
});
});
});
});
completableFutureCompletableFuture.get();
}
No exception is thrown (even when using exceptionally) and what I see is that the console output is
first
second
third // appears sometimes
Now, obviously this code has no real production value but this is a representation of a case where your code has an unknown number of nestings where each, or some of them, create CompleteableFutures which won't be executed.
Any explanation (and example on how to fix) would be greatly appreciated
The reason why this doesn't work is because in your simple test the VM exits before all tasks are completed.
When you call completableFutureCompletableFuture.get() only the first nesting of the futures is guaranteed to have finished. The VM exits, and all threads get killed.
In other words, the first nested future could still be "uncompleted" as its thread might still be busy. However, when you try to get its result with get it will of course wait until it completed and it will work as expected. Just try:
completableFutureCompletableFuture.get().get().get().get().get()
... then you force all futures to have completed and everything works as expected.
It happens because your CompletableFuture are executed asynchronously but your program terminates before the fifth call happens (I assume you ran it in a single main and returned just after creating your futures).
As you may not know how many Future are stacked in your Future (due to type erasure). You may want to perform a recursive .get().
See :
public static void main(String[] args) throws InterruptedException, ExecutionException {
CompletableFuture<?> futures = getFutures();
recursiveGet(futures);
System.out.println("finished");
}
public static CompletableFuture<?> getFutures() {
CompletableFuture<CompletableFuture<CompletableFuture<CompletableFuture<CompletableFuture<CompletableFuture<Object>>>>>> compositeCompletable = CompletableFuture.supplyAsync(() -> {
System.out.println("first");
return CompletableFuture.supplyAsync(() -> {
System.out.println("second");
return CompletableFuture.supplyAsync(() -> {
System.out.println("third");
return CompletableFuture.supplyAsync(() -> {
System.out.println("fourth");
return CompletableFuture.supplyAsync(() -> {
System.out.println("fifth");
return CompletableFuture.completedFuture(null);
});
});
});
});
});
return compositeCompletable;
}
public static void recursiveGet(Future<?> future) throws InterruptedException, ExecutionException{
Object result = future.get();
if(result instanceof Future){
recursiveGet((Future<?>) result);
}
}
which returns
first
second
third
fourth
fifth
finished
Just tested this and it works. I think the reason why is not working for you is because you run in in a main method and you did not wait to complete. I did a Thread.sleep(1000) after your code and it worked. The best way would be to wai for termination: completableFutureCompletableFuture.get().get().get().get().get()
Related
From CompletableFuture javadocs:
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.
and looking into CompletableFuture.complete() it calls postComplete() which seems to pop off the dependent chains and tries to complete them.
To test my understanding, I wrote a simple program
import java.util.concurrent.*;
public class TestCompletableFuture {
public static void main(String[] args) throws Exception {
CompletableFuture<Void> future = new CompletableFuture<Void>()
.whenComplete((res, exc) -> {
System.out.println("inside handle.");
if (exc != null) {
System.out.println("exception.");
}
System.out.println("completed.");
}
);
future.completeExceptionally(new Exception("exception"));
System.out.println("done.");
}
}
the output of the code:
done.
From my understanding, when the main thread calls future.completeExceptionally() it should invoke the function passed into CompletableFuture.whenComplete().
Why is this not the case?
This is because you are completing the wrong future. You need to get a reference to the first stage and complete that to see the whenComplete in action:
public class TestCompletableFuture {
public static void main(String[] args) throws Exception {
// get reference
CompletableFuture<Void> future = new CompletableFuture<>();
// configure the action that to be run when the future is complete
CompletableFuture<Void> future2 = future
.whenComplete((res, exc) -> {
System.out.println("inside handle.");
if (exc != null) {
System.out.println("exception.");
}
System.out.println("completed.");
}
);
future.completeExceptionally(new Exception("exception"));
System.out.println("done.");
}
}
So, now the code speaks for itself... When the future is complete run that action (res, exc) -> {...}. And then just trigger that completion on the future by calling completeExceptionally(...) on it.
Another thing to note is that all of the above stages (futures) are completed exceptionally now:
System.out.println(future.isDone()); // true
System.out.println(future2.isDone()); // true
System.out.println(future.isCompletedExceptionally()); // true
System.out.println(future2.isCompletedExceptionally()); // true
I have a problem with concurrent programming in Java. I am working on my bachelor thesis and I have to make several methods which will return me a String value. In the Futures TriggerMessageFututre and getMeterValuesFuture is a process running which takes between 1-5 seconds and returns a String Value when it's finished.
The problem is now that future.get() is blocking my main thread. I want to call the TriggerMessage and the getMeterValue methode in my main without blocking my main thread and get their answer as a return value when they are finished. I wasn't able to find a way to solve my problem, because either it was a solution without return value or it was a solution which blocked the thread.
private String TriggerMessage(String Messagetyp) throws InterruptedException, ExecutionException{
Future<String> future = new communicator().TriggerMessageFuture(queue,centralSystem,Messagetyp);
while(!future.isDone()) {
System.out.println("[TriggerMessage]: Calculating... ");
Thread.sleep(500);
}
String result = future.get(); //blocking
return result;
}
private String getMeterValue(String key) throws Exception{
Future<String> future = new communicator().getMeterValueFuture(queue,centralSystem,key);
while(!future.isDone()) {
System.out.println("[getMeterValue]: Calculating...");
Thread.sleep(500);
}
String result = future.get(); //blocking
return result;
}
It depends on what main thread are you referring to, plus if you can use CompletableFutures instead of plain old Java Futures.
Using the main(String[] args) thread
It's not possible to do it without any form of blocking. If you are not blocking on get, you'll have to block on a BlockingQueue implementation, otherwise the main thread just ends.
Using the Swing Event Dispatch thread
You'd need to submit a continuation task which is not possible with Future.get from the outside. So either you include this submission inside the task Future has been created for, or switch to CompletableFuture
ExecutorService exec = ...
Future<?> future = exec.submit(() -> {
var value = someCalculation();
SwingUtilities.invokeLater(() -> {
useValueOnEDT(value);
});
});
or
CompletableFuture<ValueType> cf = ...
cf.whenComplete((value, error) -> {
SwingUtilities.invokeLater(() -> {
if (error != null) {
handleErrorOnEdt(error);
} else {
useValueOnEDT(value);
}
});
});
Android Main Thread
The idea is the same as with Swing, but you'll have to use a Handler
// given value
new Handler(Looper.getMainLooper()).post(() -> {
useValueOnMainLooper(value);
});
You can wrap the Future into a CompletableFuture like so
static <T> CompletableFuture<T> from(Future<T> future) {
var delegate = new CompletableFuture<T>();
CompletableFuture.runAsync(() -> {
try {
delegate.complete(future.get());
} catch (Throwable e) {
delegate.completeExceptionally(e);
}
});
return delegate;
}
And then use that CompletableFuture to asynchronously handle the completion via its various then... and when... methods.
If i try to emit onNext on different thread's, on subscribing it dosent catch the stream on next elements.
public static Observable<Student> getStudents()
{
return Observable.create(e -> {
for(int i : Arrays.asList(1,2,3))
{
Thread t = new Thread(() -> {
e.onNext(new Student("anirba", i));
});
t.start();
}
e.onComplete();
});
}
On sunbscribing to this observable i dont get any responseenter code here
Observable<Student> observer = getStudents();
observer.subscribe(i -> System.out.println(i));
You are creating three threads inside the create method and each is adding an object of Student to stream. The reason why you are not getting any output is all these three threads will be running independently and based on thread scheduler it will be executed. In your case, the onComplete() method might get called before all these three threads add data into the Observable stream. and on-call of onComplete, the stream will be closed and no more data will be accepted by the stream. To make it work just to the below changes, it should work as you are expecting.
public static Observable<Student> getStudents() {
return Observable.create(e -> {
for(int i : Arrays.asList(1,2,3)) {
Thread t = new Thread(() -> {
e.onNext(new Student("anirba", i));
});
t.start();
}
Thread.sleep(1000);
e.onComplete();
});
}
java.util.concurrent.Executor is the right API now for running tasks. To block the current thread you can use CountDownLatch and release it when all tasks are terminated.
ExecutorService executor = Executors.newCachedThreadPool(); // choose the right one
public Observable<Student> getStudents() {
return Observable.<Student>create(emitter -> {
List<Integer> source = Arrays.asList(1, 2, 3);
CountDownLatch latch = new CountDownLatch(source.size());
source
.forEach(i ->
executor.submit(() -> {
emitter.onNext(new Student("anirba", i));
latch.countDown();
}));
latch.await();
emitter.onComplete();
}).serialize();
}
And elsewhere don't forget to call shutdown() on the executor.
You may also add serialize() operator to avoid onnext() calls to overlap.
From the contract :
Observables must issue notifications to observers serially (not in
parallel). They may issue these notifications from different threads,
but there must be a formal happens-before relationship between the
notifications.
For the perpose of testing you can add Thread.sleep(x) to see your loggin. I've already answerd this before here
public static void main(String[] args) throws InterruptedException {
getStudents()
.subscribe(i -> System.out.println(i));
Thread.sleep(2000);
}
Vertx docs suggests to use executeBlocking() method when one needs to call blocking API. On the other hand Vertx also offers a notion of Future which basically do the same thing. But the executeBlocking() method isn't static. It is also not a simple wrapper around Future, and if you look at its implementation you'll see that it's pretty complex. What's the difference between these two?
Assume that I want to execute some long running task in an async way. Is there any difference between these two methods?
method 1:
doTheJob() {
Future<Void> future = Future.future();
executeLongRunningBlockingOperation();
future.complete();
return future;
}
doTheJob().setHandler(asyncResult -> {
// ... handle result
});
method 2:
vertx.executeBlocking(future -> {
executeLongRunningBlockingOperation();
future.complete();
}, res -> {
// ... handle result
});
Your first example is not a correct usage of Future. The call to executeLongRunningBlockingOperation() will block the main thread until that method has completed — i.e. nothing else can happen until the blocking operation finishes. In your second example the blocking call is spun off into a background thread and other things continue to happen while it executes.
To illustrate this with a more complete example, this code:
public void executeLongRunningBlockingOperation() {
Thread.sleep(5000);
}
public Future<Void> doTheJob() {
System.out.println("Doing the job...");
Future<Void> future = Future.future();
executeLongRunningBlockingOperation();
// this line will not be called until executeLongRunningBlockingOperation returns!
future.complete();
// nor will this method! This means that the method won't return until the long operation is done!
return future;
}
public static void main(String[] args) {
doTheJob().setHandler(asyncResult -> {
System.out.println("Finished the job");
});
System.out.println("Doing other stuff in the mean time...");
}
Will produce the following output:
Doing the job...
Finished the job
Doing other stuff in the mean time...
Whereas this code (using the executeBlocking):
...
public Future<Void> doTheJob() {
System.out.println("Doing the job...");
Future<Void> future = Future.future();
Vertx vertx = Vertx.vertx();
vertx.executeBlocking(call -> {
executeLongRunningBlockingOperation();
call.complete;
}, result -> {
// this will only be called once the blocking operation is done
future.complete();
});
// this method returns immediately since we are not blocking the main thread
return future;
}
...
Will produce:
Doing the job...
Doing other stuff in the mean time...
Finished the job
If you'd like to develop a better understanding of Vert.x I'd recommend the following hands-on tutorials:
https://vertx.io/docs/guide-for-java-devs/
http://escoffier.me/vertx-hol/
This is very basic recursion for CompletableFuture, I want to make reliable system so each time got exception to restart process again, I'm believing it has too much issues and want to get your feedback about it
private CompletableFuture<?> recursion() {
return CompletableFuture.runAsync(() -> {
//code here
}).handleAsync((v, th) -> {
if (th != null)
return this.recursion();
else
return v;
});
}
Edit1:
int tries =5;
private CompletableFuture<?> recursion() {
return CompletableFuture.runAsync(() -> {
//code here
}).handleAsync((v, th) -> {
if (th != null && tries-- > 0){
Thread.sleep(1000);
return this.recursion();
}else
return v;
});
}
Edit2:
cleaning code as the return CompletableFuture<?> has no need so hanged it to be returning void considering #Holger comment and using AtomicInteger for tries
AtomicInteger tries =5;
private void recursion() {
CompletableFuture.runAsync(() -> {
//code here
}).whenCompleteAsync((v, th) -> {
if (th != null && ( tries.getAndDecrement() > 0 ) ){
Thread.sleep(1000);
this.recursion();
});
}
please send me you feedback,I'm arguing but really appreciate it.
Generally, simply retrying an operation when an exception occurs, without ever dealing with the exception to analyze the reason of the failure, is far away from creating a reliable system.
Nevertheless, if you want to implement retries, your code fails to do this correctly.
Your code happens to get accepted by the compiler because you use an action which doesn’t produce a value and return a CompletableFuture<?>. This hides the problems with your code:
The bifunction passed to handleAsync is supposed to provide the result value but you are calling this.recursion() which produces a CompletableFuture<?>. The compiler doesn’t mind that in the non-exceptional case v is returned, as Void and CompletableFuture<?> have a common super type, Object, so the entire method is effectively returning a CompletableFuture<Object> which is compatible with the return type CompletableFuture<?>.
If you declared the return type as CompletableFuture<Void>, the logical error became recognizable immediately: in the exceptional case you are launching another asynchronous operation but since you are not checking it’s result but just returning a CompletableFuture<?>, which is then treated as Object, the caller will never notice whether the retry (or subsequent retries) failed. The caller will always receive a CompletableFuture<?> which reports a success, holding either (Void)null or a CompletableFuture<?> as result value.
Generally, you shouldn’t use recursion for a repetition. There is no reason to do so. Let’s demonstrate the logic with an action which returns a value:
CompletableFuture<String> performAsyncAction() {
Supplier<String> action=() -> {
if(Math.random()>0.2)
throw new IllegalStateException("simulated failure");
return "value implying success";
};
int retries=5;
return CompletableFuture.supplyAsync(() -> {
try { return action.get(); }
catch(Throwable t) {
for(int i=0; i<retries; i++) try {
Thread.sleep(1000);
return action.get();
} catch(Throwable next) { t.addSuppressed(next); }
throw t;
}
});
}
It’s easy to adapt to use a Runnable, runAsync and CompletableFuture<Void>.
Update: if you just want to schedule a retry without giving a feedback to the initiator, you may implement it without blocking a thread by waiting for the delay to elapse:
static ScheduledExecutorService e = Executors.newSingleThreadScheduledExecutor();
static void performAsyncAction(Runnable r, int tries, long delay, TimeUnit u) {
if(tries>0)
e.execute(()-> { try { r.run(); } catch(Throwable t) {
e.schedule(()->performAsyncAction(r, tries-1, delay, u), delay, u);
}});
}
This uses recursion as it settles on lambda expressions. The same would work without recursion if you use an inner class:
static ScheduledExecutorService e = Executors.newSingleThreadScheduledExecutor();
static void performAsyncAction(Runnable r, int tries, long delay, TimeUnit u) {
if(tries>0)
e.execute(new Runnable() {
int left = tries;
public void run() {
try { r.run(); } catch(Throwable t) {
if(--left > 0) e.schedule(this, delay, u);
}
}
});
}