I have a class which issues concurrent requests to two dependent services using CompletableFutures.
My code looks like this:
#Builder
#Slf4j
public class TestClass {
#NonNull private final ExecutorService threadPool = Executors.newFixedThreadPool(2);
#NonNull private final dependency1Client;
#NonNull private final dependency2Client;
public void myMethod() {
RequestObject1 firstDependencyRequest = RequestObject1.builder()
.attribute1("someValue")
.attribute2("secondValue");
CompletableFuture<ResultStructure1> future1 = CompletableFuture.supplyAsync(() -> dependency1Client.call(firstDependencyRequest), threadPool);
RequestObject2 secondDependencyRequest = RequestObject2.builder()
.attribute1("someValue")
.attribute2("secondValue");
CompletableFuture<ResultStructure2> future2 = CompletableFuture.supplyAsync(() -> dependency2Client.call(secondDependencyRequest), threadPool);
try {
CompletableFuture finalFuture = CompletableFuture.allOf(future1, future2);
} catch (ExecutionException|InterruptedException e) {
log.error("Exception calling dependency", e);
throw new RuntimeException(e);
}
}
}
I need the results from the two calls to the dependent services. How do I get them without performing a blocking call? I was initially thinking that I'd do future1 .get(), but that's a blocking call and I'll have to wait until I have the results from the first API call.
Is there a way to obtain the results from both the calls?
As the JavaDoc of CompletableFuture.allOf() indicates:
Otherwise, the results, if any, of the given CompletableFutures are not reflected in the returned CompletableFuture, but may be obtained by inspecting them individually.
What this means is indeed that you have to call join() or get() on them. It will not block if you do that in the chain after your allOf(), since it already guarantees that all of them are already completed.
Note that in your particular case, if you only have 2 futures, it is probably simpler to use thenCombine() which gives you access to the 2 results more easily.
Related
I've been developing Rest API's in Java. I want to convert them it into Async. The Two options I see is DeferredResult and CompletableFeature.
I don't seem to be find the difference between these two, and when to chose over another.
Any real time examples would be appreciated.
DeferredResult is spring class and it is just a container of the result (as its name implies) so we need to explicitly use some kind of thread pool (ForkJoinPool for example) to run our processing asynchronously. CompletableFuture is part of java.util.concurrent and allow to run the processing asynchronously. It implements Future and basically have the ability to compose, combine and execute asynchronous computation steps.
Simple example of both options:
#GetMapping(value = "/deferredResult")
public DeferredResult<Boolean> useDeferredResult() {
DeferredResult<Boolean> deferredResult = new DeferredResult<>();
deferredResult.onCompletion(() -> logResult((Boolean)deferredResult.getResult()));
ForkJoinPool.commonPool().submit(() -> {
deferredResult.setResult(processRequest());
});
return deferredResult;
}
#GetMapping(value = "/completableFuture")
public CompletableFuture<Boolean> useCompletableFuture() {
return CompletableFuture.supplyAsync(this::processRequest)
.thenApplyAsync(this::logResult);
}
private boolean logResult(Boolean result) {
System.out.println("Result: " + result);
return true;
}
private boolean processRequest() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
Notes:
By default, Spring will execute the CompletableFuture actions by
ForkJoinPool (can be configured).
In the case of DeferredResult, the logResult will be executed by the servlet container (for example Tomcat) worker thread - not nessecrally the one got the request at the beginning.
You can (while I don't see any
reason to) run processing asynchronously with CompletableFuture and
return DeferredResult.
With DeferredResult you can register more callbacks, like onCompleted - For example onError, etc. See here.
CompletableFuture has a lot options to compose actions. See here.
IMHO, CompletableFuture is more elegant and has more capabilities.
Also, here you have a working example project.
Im using Java 1.8, dropwizard 1.3.5, and swagger inflection 1.0.13 for my API.
I have a method which takes an HTTP Request, delays 20 seconds, then returns a 200 status code response:
public ResponseContext delayBy20Seconds(RequestContext context) {
ResponseContext response = new ResponseContext().contentType(MediaType.APPLICATION_JSON_TYPE);
Thread.sleep(20000);
response.status(Response.Status.OK);
return response;
}
Say I want to return a 400 status code if the operation (which in this case takes 20 seconds), takes more than 15 seconds. How would I achieve this?
One way to do it without additional libraries is by using the java.util.concurrent package. The surest way to cancel a long-running task like this is by running it in a separate thread.
import java.util.concurrent.*;
...
private ExecutorService exec = Executors.newSingleThreadExecutor();
public ResponseContext delayBy20Seconds(RequestContext context) {
Callable<ResponseContext> task = new Callable<ResponseContext>() {
#Override
public ResponseContext call() throws Exception {
Thread.sleep(20000);
return new ResponseContext().contentType(MediaType.APPLICATION_JSON_TYPE);
}
};
List<Callable<ResponseContext>> tasks = new ArrayList<>();
tasks.add(task);
List<Future<ResponseContext>> done = exec.invokeAll(tasks, 15, TimeUnit.SECONDS);
Future<ResponseContext> task1 = done.get(0);
if (task1.isCancelled()) {
return some Error Response;
}
return task1.get();
}
Your ExecutorService should not be static, because you don't want to share it between threads for this particular use.
The Callable<ResponseContext> implementation is where the work for the long-running task is done. And as it should be obvious in the exec.invokeAll call we tell it how much we're willing to wait. The list of Futures returned will always contain as many elements as the list of tasks, so there's no need to check it for emptiness. We just have to check if the task completed or not.
You could use something like the TimeLimiter from the Google Guava library. This allows you to wrap a callable in an operation that you can call with Timeout. If the callable does not complete the operation in time, it will throw a TimeoutException which you can catch and return a 400 response.
As an example:
TimeLimiter timeLimiter = new SimpleTimeLimiter();
try {
String result = timeLimiter.callWithTimeout(
() -> doSomeHeavyWeightOperation(), 15, TimeUnit.SECONDS);
} catch (TimeoutException e) {
// return 400
}
I've been looking at Go's goroutines lately and thought it would be nice to have something similar in Java. As far as I've searched the common way to parallelize a method call is to do something like:
final String x = "somethingelse";
new Thread(new Runnable() {
public void run() {
x.matches("something");
}
}).start();
Thats not very elegant. Is there a better way of doing this? I needed such a solution in a project so I decided to implement my own wrapper class around a async method call.
I published my wrapper class in J-Go. But I don't know if it is a good solution. The usage is simple:
SampleClass obj = ...
FutureResult<Integer> res = ...
Go go = new Go(obj);
go.callLater(res, "intReturningMethod", 10); //10 is a Integer method parameter
//... Do something else
//...
System.out.println("Result: "+res.get()); //Blocks until intReturningMethod returns
or less verbose:
Go.with(obj).callLater("myRandomMethod");
//... Go away
if (Go.lastResult().isReady()) //Blocks until myRandomMethod has ended
System.out.println("Method is finished!");
Internally I'm using a class that implements Runnable and do some Reflection work to get the correct method object and invoking it.
I want some opinion about my tiny library and on the subject of making async method calls like this in Java. Is it safe? Is there already a simplier way?
I just discovered that there is a cleaner way to do your
new Thread(new Runnable() {
public void run() {
//Do whatever
}
}).start();
(At least in Java 8), you can use a lambda expression to shorten it to:
new Thread(() -> {
//Do whatever
}).start();
As simple as making a function in JS!
Java 8 introduced CompletableFuture available in package java.util.concurrent.CompletableFuture, can be used to make a asynch call :
CompletableFuture.runAsync(() -> {
// method call or code to be asynch.
});
You may wish to also consider the class java.util.concurrent.FutureTask.
If you are using Java 5 or later, FutureTask is a turnkey implementation of "A cancellable asynchronous computation."
There are even richer asynchronous execution scheduling behaviors available in the java.util.concurrent package (for example, ScheduledExecutorService), but FutureTask may have all the functionality you require.
I would even go so far as to say that it is no longer advisable to use the first code pattern you gave as an example ever since FutureTask became available. (Assuming you are on Java 5 or later.)
i don't like the idea of using Reflection for that.
Not only dangerous for missing it in some refactoring, but it can also be denied by SecurityManager.
FutureTask is a good option as the other options from the java.util.concurrent package.
My favorite for simple tasks:
Executors.newSingleThreadExecutor().submit(task);
little bit shorter than creating a Thread (task is a Callable or a Runnable)
You can use the Java8 syntax for CompletableFuture, this way you can perform additional async computations based on the result from calling an async function.
for example:
CompletableFuture.supplyAsync(this::findSomeData)
.thenApply(this:: intReturningMethod)
.thenAccept(this::notify);
More details can be found in this article
You can use #Async annotation from jcabi-aspects and AspectJ:
public class Foo {
#Async
public void save() {
// to be executed in the background
}
}
When you call save(), a new thread starts and executes its body. Your main thread continues without waiting for the result of save().
You can use Future-AsyncResult for this.
#Async
public Future<Page> findPage(String page) throws InterruptedException {
System.out.println("Looking up " + page);
Page results = restTemplate.getForObject("http://graph.facebook.com/" + page, Page.class);
Thread.sleep(1000L);
return new AsyncResult<Page>(results);
}
Reference: https://spring.io/guides/gs/async-method/
Java also provides a nice way of calling async methods. in java.util.concurrent we have ExecutorService that helps in doing the same. Initialize your object like this -
private ExecutorService asyncExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
and then call the function like-
asyncExecutor.execute(() -> {
TimeUnit.SECONDS.sleep(3L);}
You can use AsyncFunc from Cactoos:
boolean matches = new AsyncFunc(
x -> x.matches("something")
).apply("The text").get();
It will be executed at the background and the result will be available in get() as a Future.
It's probably not a real solution, but now - in Java 8 - You can make this code look at least a little better using lambda expression.
final String x = "somethingelse";
new Thread(() -> {
x.matches("something");
}
).start();
And You could even do this in one line, still having it pretty readable.
new Thread(() -> x.matches("something")).start();
This is not really related but if I was to asynchronously call a method e.g. matches(), I would use:
private final static ExecutorService service = Executors.newFixedThreadPool(10);
public static Future<Boolean> matches(final String x, final String y) {
return service.submit(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
return x.matches(y);
}
});
}
Then to call the asynchronous method I would use:
String x = "somethingelse";
try {
System.out.println("Matches: "+matches(x, "something").get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
I have tested this and it works. Just thought it may help others if they just came for the "asynchronous method".
There is also nice library for Async-Await created by EA: https://github.com/electronicarts/ea-async
From their Readme:
With EA Async
import static com.ea.async.Async.await;
import static java.util.concurrent.CompletableFuture.completedFuture;
public class Store
{
public CompletableFuture<Boolean> buyItem(String itemTypeId, int cost)
{
if(!await(bank.decrement(cost))) {
return completedFuture(false);
}
await(inventory.giveItem(itemTypeId));
return completedFuture(true);
}
}
Without EA Async
import static java.util.concurrent.CompletableFuture.completedFuture;
public class Store
{
public CompletableFuture<Boolean> buyItem(String itemTypeId, int cost)
{
return bank.decrement(cost)
.thenCompose(result -> {
if(!result) {
return completedFuture(false);
}
return inventory.giveItem(itemTypeId).thenApply(res -> true);
});
}
}
Suppose I have some async computation, such as:
CompletableFuture
.supplyAsync(() -> createFoo())
.thenAccept(foo -> doStuffWithFoo(foo));
Is there a nice way to provide a default value for foo if the async supplier times out according to some specified timeout? Ideally, such functionality would attempt to cancel the slow-running supplier as well. For example, is there standard library functionality that is similar to the following hypothetical code:
CompletableFuture
.supplyAsync(() -> createFoo())
.acceptEither(
CompletableFuture.completedAfter(50, TimeUnit.MILLISECONDS, DEFAULT_FOO),
foo -> doStuffWithFoo(foo));
Or perhaps even better:
CompletableFuture
.supplyAsync(() -> createFoo())
.withDefault(DEFAULT_FOO, 50, TimeUnit.MILLISECONDS)
.thenAccept(foo -> doStuffWithFoo(foo));
I know about get(timeout, unit), but am wondering if there's a nicer standard way of applying a timeout in an asynchronous and reactive fashion as suggested in the code above.
EDIT: Here's a solution that's inspired by Java 8: Mandatory checked exceptions handling in lambda expressions. Why mandatory, not optional?, but unfortunately it blocks a thread. If we rely on createFoo() to asynchronously check for timeout and throw its own timeout exception it would work without blocking a thread, but would place more burden on the creator of the supplier and would still have the cost of creating an exception (which can be expensive without "fast throw")
static <T> Supplier<T> wrapped(Callable<T> callable) {
return () -> {
try {
return callable.call();
} catch (RuntimeException e1) {
throw e1;
} catch (Throwable e2) {
throw new RuntimeException(e2);
}
};
}
CompletableFuture
.supplyAsync(wrapped(() -> CompletableFuture.supplyAsync(() -> createFoo()).get(50, TimeUnit.MILLISECONDS)))
.exceptionally(e -> "default")
.thenAcceptAsync(s -> doStuffWithFoo(foo));
CompletableFuture.supplyAsync is just a helper method that creates a CompletableFuture for you, and submits the task to the ForkJoin Pool.
You can create your own supplyAsync with your requirements like this:
private static final ScheduledExecutorService schedulerExecutor =
Executors.newScheduledThreadPool(10);
private static final ExecutorService executorService =
Executors.newCachedThreadPool();
public static <T> CompletableFuture<T> supplyAsync(
final Supplier<T> supplier, long timeoutValue, TimeUnit timeUnit,
T defaultValue) {
final CompletableFuture<T> cf = new CompletableFuture<T>();
// as pointed out by Peti, the ForkJoinPool.commonPool() delivers a
// ForkJoinTask implementation of Future, that doesn't interrupt when cancelling
// Using Executors.newCachedThreadPool instead in the example
// submit task
Future<?> future = executorService.submit(() -> {
try {
cf.complete(supplier.get());
} catch (Throwable ex) {
cf.completeExceptionally(ex);
}
});
//schedule watcher
schedulerExecutor.schedule(() -> {
if (!cf.isDone()) {
cf.complete(defaultValue);
future.cancel(true);
}
}, timeoutValue, timeUnit);
return cf;
}
Creating the CompletableFuture with that helper is as easy as using the static method in CompletableFuture:
CompletableFuture<String> a = supplyAsync(() -> "hi", 1,
TimeUnit.SECONDS, "default");
To test it:
a = supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
// ignore
}
return "hi";
}, 1, TimeUnit.SECONDS, "default");
In Java 9, there will be completeOnTimeout(T value, long timeout, TimeUnit unit), which does what you want, although it does not cancel the slow supplier.
There is also a orTimeout(long timeout, TimeUnit unit), which completes exceptionally in case on a timeout.
DZone has a good article how to solve this: https://dzone.com/articles/asynchronous-timeouts
I'm not sure about the copyright of the code, hence I can't copy it here. The solution is very much like the one from Dane White but it uses a thread pool with a single thread plus schedule() to avoid wasting a thread just to wait for the timeout.
It also throws a TimeoutException instead of returning a default.
I think you'll always need an extra thread monitoring when its time to supply the default value. I'd probably go the route of having two supplyAsync calls, with the default wrapped in a utility API, linked by an acceptEither. If you'd rather wrap your Supplier, then you could use a utility API that makes the 'either' call for you:
public class TimeoutDefault {
public static <T> CompletableFuture<T> with(T t, int ms) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(ms);
} catch (InterruptedException e) { }
return t;
});
}
public static <T> Supplier<T> with(Supplier<T> supplier, T t, int ms) {
return () -> CompletableFuture.supplyAsync(supplier)
.applyToEither(TimeoutDefault.with(t, ms), i -> i).join();
}
}
CompletableFuture<Void> future = CompletableFuture
.supplyAsync(Example::createFoo)
.acceptEither(
TimeoutDefault.with("default", 1000),
Example::doStuffWithFoo);
CompletableFuture<Void> future = CompletableFuture
.supplyAsync(TimeoutDefault.with(Example::createFoo, "default", 1000))
.thenAccept(Example::doStuffWithFoo);
There's no standard library method for constructing a CompletableFuture supplied with a value after a timeout. That said, it's really simple to roll your own with minimal resource overhead:
private static final ScheduledExecutorService EXECUTOR
= Executors.newSingleThreadScheduledExecutor();
public static <T> CompletableFuture<T> delayedValue(final T value,
final Duration delay) {
final CompletableFuture<T> result = new CompletableFuture<>();
EXECUTOR.schedule(() -> result.complete(value),
delay.toMillis(), TimeUnit.MILLISECONDS);
return result;
}
It can be used with the "either" methods of CompleteableFuture:
accceptEither, acceptEitherAsync
applyToEither, applyToEitherAsync
runAfterEither, runAfterEitherAsync
One application is using a cached value if a remote service call exceeds some latency threshold:
interface RemoteServiceClient {
CompletableFuture<Foo> getFoo();
}
final RemoteServiceClient client = /* ... */;
final Foo cachedFoo = /* ... */;
final Duration timeout = /* ... */;
client.getFoos()
.exceptionally(ignoredException -> cachedFoo)
.acceptEither(delayedValue(cachedFoo, timeout),
foo -> /* do something with foo */)
.join();
In case the remote client call completes exceptionally (e.g. SocketTimeoutException), we can fail fast and use the cached value immediately.
CompletableFuture.anyOf(CompletableFuture<?>...) can be combined with this delayedValue primitive to wrap a CompletableFuture with the above semantics:
#SuppressWarnings("unchecked")
public static <T> CompletableFuture<T> withDefault(final CompletableFuture<T> cf,
final T defaultValue,
final Duration timeout) {
return (CompletableFuture<T>) CompletableFuture.anyOf(
cf.exceptionally(ignoredException -> defaultValue),
delayedValue(defaultValue, timeout));
}
This nicely simplifies the remote service call example above:
withDefault(client.getFoos(), cachedFoo, timeout)
.thenAccept(foo -> /* do something with foo */)
.join();
CompletableFutures are more accurately termed promises, as they decouple creation of the Future from its completion. Be sure to use dedicated thread pools for heavy CPU work. To create a CompletableFuture for an expensive computation, you should use the CompletableFuture#supplyAsync(Supplier, Executor) overload, as the #supplyAsync(Supplier) overload defaults to the common ForkJoinPool. The returned CompletableFuture could not cancel its task, as this functionality isn't exposed by the Executor interface. More generally, dependent CompletableFutures don't cancel their parents, e.g. cf.thenApply(f).cancel(true) does not cancel cf. I'd recommend sticking to the Futures returned by ExecutorServices if you need that functionality.
In the docs, a FutureWrapper is defined like this:
FutureWrapper is a simple Future that
wraps a parent Future.
What's a Future, why would you need to wrap it and when would you use it in App Engine?
It's the java.util.concurrent.Future<V>. The linked Javadoc is pretty clear and contains an example. For the lazy, here's a copypaste:
A Future represents the result of an
asynchronous computation. Methods are
provided to check if the computation
is complete, to wait for its
completion, and to retrieve the result
of the computation. The result can
only be retrieved using method get
when the computation has completed,
blocking if necessary until it is
ready. Cancellation is performed by
the cancel method. Additional methods
are provided to determine if the task
completed normally or was cancelled.
Once a computation has completed, the
computation cannot be cancelled. If
you would like to use a Future for the
sake of cancellability but not provide
a usable result, you can declare types
of the form Future<?> and return null
as a result of the underlying task.
Sample Usage (Note that the following
classes are all made-up.)
interface ArchiveSearcher { String search(String target); }
class App {
ExecutorService executor = ...
ArchiveSearcher searcher = ...
void showSearch(final String target)
throws InterruptedException {
Future<String> future
= executor.submit(new Callable<String>() {
public String call() {
return searcher.search(target);
}});
displayOtherThings(); // do other things while searching
try {
displayText(future.get()); // use future
} catch (ExecutionException ex) { cleanup(); return; }
}
}
The FutureTask class is an
implementation of Future that
implements Runnable, and so may be
executed by an Executor. For example,
the above construction with submit
could be replaced by:
FutureTask<String> future =
new FutureTask<String>(new Callable<String>() {
public String call() {
return searcher.search(target);
}});
executor.execute(future);
Memory consistency effects: Actions
taken by the asynchronous computation
happen-before actions following the
corresponding Future.get() in another
thread.
The FutureWrapper is just a decorator for any parent Future.