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
Related
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.
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/
I'm running into a problem where occasionally my example code below will fail when running the test suite, but the tests individually always seem to pass. If I use just .get() for the spy CompletableFuture without specifying a timeout, it hangs indefinitely.
This problem occurs both on Windows, OS X, and I've tried a few different versions of the the Java 8 JDK.
I have this problem with Mockito 2.18.3 and Mockito 1.10.19.
I can run the example test suite code below sometimes 7-10 times successfully, but almost always when trying more than 10 times I'll see random test failures.
Any help would be greatly appreciated. I have also posted on the Mockito mailing list, but things look fairly quite there.
package example;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.junit.Test;
import static org.mockito.Mockito.spy;
public class MockitoCompletableFuture1Test {
#Test
public void test1() throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "ABC");
CompletableFuture<String> futureSpy = spy(future);
try {
assertEquals("ABC", futureSpy.get(1, TimeUnit.SECONDS));
} catch (TimeoutException e) {
assertEquals("ABC", future.get(1, TimeUnit.SECONDS)); // PASSES
assertEquals("ABC", futureSpy.get(1, TimeUnit.SECONDS)); // OCCASIONALLY FAILS
fail("futureSpy.get(...) timed out");
}
}
#Test
public void test2() throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "ABC");
CompletableFuture<String> futureSpy = spy(future);
try {
assertEquals("ABC", futureSpy.get(1, TimeUnit.SECONDS));
} catch (TimeoutException e) {
assertEquals("ABC", future.get(1, TimeUnit.SECONDS)); // PASSES
assertEquals("ABC", futureSpy.get(1, TimeUnit.SECONDS)); // OCCASIONALLY FAILS
fail("futureSpy.get(...) timed out");
}
}
#Test
public void test3() throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "ABC");
CompletableFuture<String> futureSpy = spy(future);
try {
assertEquals("ABC", futureSpy.get(1, TimeUnit.SECONDS));
} catch (TimeoutException e) {
assertEquals("ABC", future.get(1, TimeUnit.SECONDS)); // PASSES
assertEquals("ABC", futureSpy.get(1, TimeUnit.SECONDS)); // OCCASIONALLY FAILS
fail("futureSpy.get(...) timed out");
}
}
#Test
public void test4() throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "ABC");
CompletableFuture<String> futureSpy = spy(future);
try {
assertEquals("ABC", futureSpy.get(1, TimeUnit.SECONDS));
} catch (TimeoutException e) {
assertEquals("ABC", future.get(1, TimeUnit.SECONDS)); // PASSES
assertEquals("ABC", futureSpy.get(1, TimeUnit.SECONDS)); // OCCASIONALLY FAILS
fail("futureSpy.get(...) timed out");
}
}
#Test
public void test5() throws Exception {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "ABC");
CompletableFuture<String> futureSpy = spy(future);
try {
assertEquals("ABC", futureSpy.get(1, TimeUnit.SECONDS));
} catch (TimeoutException e) {
assertEquals("ABC", future.get(1, TimeUnit.SECONDS)); // PASSES
assertEquals("ABC", futureSpy.get(1, TimeUnit.SECONDS)); // OCCASIONALLY FAILS
fail("futureSpy.get(...) timed out");
}
}
}
When future is created (calling CompletableFuture.supplyAsync), it will also create a Thread (ForkJoinPool.commonPool-worker-N) to execute the lambda expression. That thread has a reference to the newly created object (future in our case). When the async job is finished, the thread (ForkJoinPool.commonPool-worker-N) will notify (wake up) the other thread (main) waiting for it that it has finished.
How does it know which thread is waiting for it? When you call the get() method the current thread will be saved as a field in the class and the thread will park (sleep) and will wait to be unparked by some other thread.
The problem is that futureSpy will save in its own field the current thread (main), but the async thread will try to read the information from the future object (null).
The problem doesn't always appear in your test case because if the async function is already finished, get won't put the main thread to sleep.
Reduced example
For testing purposes I've reduced you test cases to something shorter that reliably reproduces the error (except the first run):
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static org.mockito.Mockito.spy;
public class App {
public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
for (int i = 0; i < 100; i++) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "ABC";
});
CompletableFuture<String> futureSpy = spy(future);
try {
futureSpy.get(2, TimeUnit.SECONDS);
System.out.println("i = " + i);
} catch (TimeoutException ex) {
System.out.println("i = " + i + " FAIL");
}
}
}
}
In my tests the output is:
i = 0
i = 1 FAIL
i = 2 FAIL
i = 3 FAIL
According to Important gotcha on spying real objects!:
Mockito *does not* delegate calls to the passed real instance, instead it actually creates a copy of it. So if you keep the real instance and interact with it, don't expect the spied to be aware of those interaction and their effect on real instance state. […]
So basically, it will take the state of your future at the time you call spy() on it. If it is already completed, then the resulting spy will be too. Otherwise, your spy will remain uncompleted, except if you complete it yourself.
As the asynchronous completion will be performed on the original future and not on your spy, it will thus not be reflected in your spy.
The only case where this would work properly, is when you have full control over it. This means you would have created your CompletableFuture with new, wrap it in a spy, and then only use that spy.
In general however, I would advise to avoid mocking futures, as you often don't have control over how they are handled. And as stated in Mockito's Remember section:
Do not mock types you don’t own
CompletableFuture is not a type you own.
Anyway, it shouldn't be necessary to mock CompletableFuture methods, as you can control what they do based on complete() or completeExecptionally(). On the other side, it shouldn't be necessary to check whether its methods are called since:
the methods with side-effects (like complete()) can easily be asserted afterwards;
the other methods are returning values that should make your test fail if they are not used.
Basically, CompletableFuture behaves similarly to a value object, and the documentation states:
Don’t mock value objects
If you feel your test cannot be written without using a spy, try to reduce it to an MCVE and post a separate question on how to do it.
I am writing a Play2 application service method in Java that should do the following. Asynchronously call method A, and if that fails, asynchronously call method B.
To illustrate assume this interface for the backend called by the service:
public interface MyBackend {
CompletionStage<Object> tryWrite(Object foo);
CompletionStage<Object> tryCleanup(Object foo);
}
So in my service method, I want to return a Future that can complete with these:
Success of tryWrite completed
Fail of tryWrite and Success of tryCleanup completed and failing with exception of tryWrite()
(Note: Of course tryWrite() could do any cleanup itself, this is a simplified example to illustrate a problem)
The implementation of a service calling the backend like this seems difficult to me because the CompletionStage.exceptionally() method does not allow Composing.
Version 1:
public class MyServiceImpl {
public CompletionStage<Object> tryWriteWithCleanup(Object foo) {
CompletionStage<Object> writeFuture = myBackend.tryWrite(foo)
.exceptionally((throwable) -> {
CompletionStage<Object> cleanupFuture = myBackend.tryCleanup(foo);
throw new RuntimeException(throwable);
});
return writeFuture;
}
}
So version 1 calls tryCleanup(foo) in a non-blocking way, but the CompletionStage returned by tryWriteWithCleanup() will not wait for cleanupFuture to complete. How to change this code to return a future from the service that would also wait for completion of cleanupFuture?
Version 2:
public class MyServiceImpl {
public CompletionStage<Object> tryWriteWithCleanup(Object foo) {
final AtomicReference<Throwable> saveException = new AtomicReference<>();
CompletionStage<Object> writeFuture = myBackend
.tryWrite(foo)
.exceptionally(t -> {
saveException.set(t);
// continue with cleanup
return null;
})
.thenCompose((nil) -> {
// if no cleanup necessary, return
if (saveException.get() == null) {
return CompletableFuture.completedFuture(null);
}
return CompletionStage<Object> cleanupFuture = myBackend.tryCleanup(foo)
.exceptionally(cleanupError -> {
// log error
return null;
})
.thenRun(() -> {
throw saveException.get();
});
});
return writeFuture;
}
}
Version2 uses an external AtomicReference to store the failure, and makes the asynchronous second call in another thenCompose() block, if there was a failure.
All my other attempts to do so ended up so unwieldy that I don't want to paste them here.
Unfortunately CompletionStage/CompletableFuture does not provide exception handling API's with composition.
You can work around this though by relying on a handle() with a BiFunction that returns a CompletionStage. This will give you nested stages (CompletionStage<CompletionStage<Object>>) that you can the "unnest" using compose(identity()):
public CompletionStage<Object> tryWriteWithCleanup(Object foo) {
return myBackend.tryWrite(foo)
.handle((r, e) -> {
if (e != null) {
return myBackend.tryCleanup(foo)
.handle((r2, e2) -> {
// Make sure we always return the original exception
// but keep track of new exception if any,
// as if run in a finally block
if (e2 != null) {
e.addSuppressed(e2);
}
// wrapping in CompletionException behaves as if
// we threw the original exception
throw new CompletionException(e);
});
}
return CompletableFuture.completedFuture(r);
})
.thenCompose(Function.identity());
}
You may simply wait for the completion inside the handler:
public CompletionStage<Object> tryWriteWithCleanup(Object foo) {
return myBackend.tryWrite(foo).exceptionally(throwable -> {
myBackend.tryCleanup(foo).toCompletableFuture().join();
throw new CompletionException(throwable);
});
}
This will defer the completion of the result CompletionStage to the completion of the cleanup stage. Using CompletionException as wrapper will make the wrapping transparent to the caller.
However, it has some drawbacks. While the framework might utilize the thread while waiting or spawn a compensation thread, if it is a worker thread, the blocked thread might be the caller thread if the stage returned by tryWrite happens to be already completed when entering exceptionally. Unfortunately, there is no exceptionallyAsync method. You may use handleAsync instead, but it will complicate the code while still feeling like a kludge.
Further, exceptions thrown by the cleanup may shadow the original failure.
A cleaner solution may be a bit more involved:
public CompletionStage<Object> tryWriteWithCleanup(Object foo) {
CompletableFuture<Object> writeFuture = new CompletableFuture<>();
myBackend.tryWrite(foo).whenComplete((obj,throwable) -> {
if(throwable==null)
writeFuture.complete(obj);
else
myBackend.tryCleanup(foo).whenComplete((x,next) -> {
try {
if(next!=null) throwable.addSuppressed(next);
}
finally {
writeFuture.completeExceptionally(throwable);
}
});
});
return writeFuture;
}
This simply creates a CompletableFuture manually, allowing to control its completion, which will happen either directly by the action chained to tryWrite’s stage in the successful case, or by the action chained to the cleanup stage in the exceptional case. Note that the latter takes care about chaining a possible subsequent cleanup exception via addSuppressed.
I want to run CompletableFuture in a TestNG class with #Test annotation.
Below is the code snippet, recursionFuture method is called recursively to do a certain task by the main() method.
Now if I use main() as public static void main(String[] args)) then everything works as desired. But when I used main() with #Test annotation then TestNG stops the execution in between and the whole task is not performed.
What should I do to make #Test to wait until all tasks are completed by recursionFuture?
I've to use CompletableFuture for async tasks and need to use #Test also.
Any help would be appreciated. Thanks.
//public static void main(String[] args) throws FileNotFoundException, InterruptedException, ExecutionException
#Test // --> this logic of recursion with threads is problematic with testNG
public static void main() throws FileNotFoundException, InterruptedException, ExecutionException
{
System.setOut(new PrintStream(new File("/Users/Pankaj/Desktop/Thread")));
Method[] method = ConcurrencyPoC_CompletableFuture.class.getMethods();
for(int i=0; i<method.length; i++)
{
if(method[i].getName().startsWith("task"))
{
TreeMap<Object, Object> m = new TreeMap<>();
m.put(method[i].getName(), method[i]);
m.put("status", new AtomicBoolean(true));
taskmap.put(method[i].getName(), m);
}
}
//submitting tasks
ExecutorService ex = Executors.newCachedThreadPool();
CompletableFuture<?> [] arrayFutures = new CompletableFuture[3];
recursionFuture(ex, arrayFutures);
}
public static String recursionFuture(ExecutorService ex, CompletableFuture<?> [] arrayFutures)
{
try
{
//check if any of submitted future is completed - to be used in case of array
for(CompletableFuture<?> future : arrayFutures)
{
future = CompletableFuture.supplyAsync(() -> new ConcurrencyPoC_CompletableFuture().executeTask(), ex);
//storing future in a final variable for further calculation
final CompletableFuture<?> task = future;
CompletableFuture.anyOf(task).thenRunAsync(() ->
{
try {
//apply recursion only when future's output is not null, otherwise there will be hell lot of futures get created which
//don't do anything just eating up memory and executing the else block of executeTask() method.
// Latest change, as soon as any task is free, create a new array of 1 size to do the next task
if(task.get() != null)
recursionFuture(ex, new CompletableFuture[1]);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
, ex);
}
}
catch(Exception e)
{
e.printStackTrace();
}
return "ALl TASK COMPLETED";
}
There is no correspondence between TestNG #Test annotation and your completable future.
The problem is in your tast.get() method. It should be blocking running threads until all completable futures are finished.
I use Completable Future in my tests and never ever I ever got into a problem with TestNG.
The problem is one of your future's finishes, and you return to the test method instead of waiting for all the futures. You should combine all your futures with thenApplyAsync() or compose() because your Future is final you are waiting only for one future. Plus you should not use CompletbleFuture.Any() because it returns to execution when the first future is complete.