I have a code which looks similar to
public void myMethod(){
List<CompletableFuture<Void>> futures = new ArrayList<>();
//getQuestion, getAnswer, both returns a CompletableFuture<Void>
futures.add(getQuestion());
futures.add(getAnswer());
// make sure all the futures are executed.
CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join();
}
Any pointers on how can I like test if the futures array was of size 2 after the execution of myMethod()*
There is no point in testing the size of the array. In Java, arrays never change their size, which also applies to the array returned by futures.toArray(…). If the size of the array was wrong, it implied that the toArray implementation of the particular collection already returned an array of the wrong size.
You can make the code more robust by using futures.toArray(new CompletableFuture[0])), letting the toArray implementation create an array of the right size instead of passing in a presized array. As explained in this article, it’s actually even faster, contrary to the old myths.
Of course, for a fixed number of futures, there’s no need to translate between collection and array at all. You could use
public void myMethod() {
CompletableFuture<?>[] futures = { getQuestion(), getAnswer() };
// make sure all the futures are executed.
CompletableFuture.allOf(futures).join();
}
The contract of CompletableFuture.allOf is to return a future that will be completed when all futures are completed and join() will unconditionally wait for that completion. There is nothing that would need to be checked. If any of the future completed exceptionally, the join() method will throw an exception, either a CompletionException having the original exception as a cause or a CancellationException when the exceptional completion was caused by cancellation.
You could split the method in two:
public void myMethod(){
List<CompletableFuture<Void>> futures = constructFutures();
// make sure all the futures are executed.
CompletableFuture
.allOf(futures.toArray(new CompletableFuture[futures.size()]))
.join();
}
List<CompletableFuture<Void>> constructFutures() {
List<CompletableFuture<Void>> futures = new ArrayList<>();
//getQuestion, getAnswer, both returns a CompletableFuture<Void>
futures.add(getQuestion());
futures.add(getAnswer());
return futures;
}
And add the test for constructFutures().
Related
I can't find out how to wrap a synchronous method with Resilience4j so that it returns a CompletableFuture, although this seems to be part of Resilience4j's target area.
Especially since the synchronous method I want to wrap can throw an Exception.
What I want in pseudo code:
boolean void syncMethod(Parameter param) throws Exception {
// May throw Exception due to connection/authorization problems.
}
CompletableFuture<Boolean> asyncResilience4jWrapper() {
CompletableFuture<Boolean> result =
...
Resilience4j magic around "syncMethod(param)".
Trying 4 calls, interval between calls of 100 ms.
...;
return result;
}
Resilience4j should just try to call the method 4 times until it gives up, with intervals between the calls of 100 ms and then complete the asynchronous call.
The asyncResilience4jWrapper caller should just get back a CompletableFuture which doesn't block and don't care about any of that.
The really hard part seems to be to get it running for a method with a parameter, throwing an exception!
just do
CompletableFuture<Boolean> asyncResilience4jWrapper(Parameter param) {
return CompletableFuture<Boolean> future = Decorators.ofCallable(() -> syncMethod(param))
.withThreadPoolBulkhead(threadPoolBulkhead)
.withTimeLimiter(timeLimiter, scheduledExecutorService)
.withCircuitBreaker(circuitBreaker)
.withRetry(retry)
.withFallback(asList(TimeoutException.class, CallNotPermittedException.class, BulkheadFullException.class),
throwable -> "Hello from Recovery")
.get().toCompletableFuture();
}
I can't find out how to wrap a synchronous method with Resilience4j so that it returns a CompletableFuture, although this seems to be part of Resilience4j's target area.
Especially since the synchronous method I want to wrap can throw an Exception.
What I want in pseudo code:
boolean void syncMethod() throws Exception {
// May throw Exception due to connection/authorization problems.
}
CompletableFuture<Boolean> asyncResilience4jWrapper() {
CompletableFuture<Boolean> result =
...
Resilience4j magic around "syncMethod()".
Trying 4 calls, interval between calls of 100 ms.
...;
return result;
}
Resilience4j should just try to call the method 4 times until it gives up, with intervals between the calls of 100 ms and then complete the asynchronous call.
The asyncResilience4jWrapper caller should just get back a CompletableFuture which doesn't block and don't care about any of that.
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(3);
TimeLimiter timeLimiter = TimeLimiter.of(Duration.ofSeconds(1));
CompletableFuture<Boolean> future = Decorators.ofCallable(() -> syncMethod)
.withThreadPoolBulkhead(threadPoolBulkhead)
.withTimeLimiter(timeLimiter, scheduledExecutorService)
.withCircuitBreaker(circuitBreaker)
.withFallback(asList(TimeoutException.class, CallNotPermittedException.class, BulkheadFullException.class),
throwable -> "Hello from Recovery")
.get().toCompletableFuture();
Just add withRetry below the CircuitBreaker.
I was developing a JavaFX app and I was supplying the JavaFX tasks in an ExecutorService submit method. Also I was trying to get the return value of the Task in the return value of the submit in a Future object. Then I discovered that ExecutorService only returns value when you submit a Callable object, and JavaFX Tasks are runnables despite having a call method. so is there any workaround for this problem?
I tried and solved my problem this way but I'm open to suggestions when I don't want to write my own class.
My main method:
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Semaphore semaphore = new Semaphore(1);
List<Integer> list = IntStream.range(0,100).boxed().collect(Collectors.toList());
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
List<Integer> sendingList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
sendingList.add(iterator.next());
}
System.out.println("SUBMITTING");
Future<Integer> future = executorService.submit((Callable<Integer>) new TestCallable(sendingList,semaphore));
System.out.println(future.get());
semaphore.acquire();
}
executorService.shutdown();
System.out.println("COMPLETED");
}
My TestCallable class:
class TestCallable extends Task<Integer> implements Callable<Integer> {
private Random random = new Random();
private List<Integer> list;
private Semaphore semaphore;
TestCallable(List<Integer> list, Semaphore semaphore) {
this.list = list;
this.semaphore = semaphore;
}
#Override
public Integer call(){
System.out.println("SENDING");
System.out.println(list);
try {
Thread.sleep(1000+random.nextInt(500));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("RECEIVED");
semaphore.release();
return list.size();
}
}
Task extends java.util.concurrent.FutureTask which in turn implements the Future interface. This means you can use a Task just like a Future.
Executor executor = ...;
Task<?> task = ...;
executor.execute(task);
task.get(); // Future method
This will cause the thread calling get() to wait until completion. However, a Task's purpose is to communicate the progress of a background process with the JavaFX Application Thread. It's close relationship to the GUI means you will most likely be launching a Task from the FX thread. This will lead to get() being called on the FX thread which is not what you want as it will freeze the GUI until get() returns; you might as well have just called Task.run directly.
Instead, you should be using the asynchronous functionality provided by Task. If you want to retrieve the value when the Task completes successfully you can use the onSucceeded property or listen to the value/state property. There's also ways to listen for failure/cancellation.
Executor executor = ...;
Task<?> task = ...;
task.setOnSucceeded(event -> handleResult(task.getValue()));
task.setOnFailed(event -> handleException(task.getException()));
executor.execute(task);
If you don't need the functionality provided by Task then it would probably be best to simply use Runnable or Callable directly.
It's not very clear what you want to do here.
Firstly, your Semaphore does nothing because you used Executors.newSingleThreadExecutor(), which already guarantees that only one task can run at any point in time.
Secondly, like what #Slaw mentioned, you are potentially blocking on JavaFX Application thread, depending on your actual implementation (your example isn't really a JavaFX application).
Next, ExecutorService has 2 main overloads for submit().
The first overload takes in a Callable. This overload allows you to retrieve the value returned by the Callable (by calling get() on the returned Future), because Callable refers to something that is can be called - it can return value.
The second overload takes in a Runnable. Since Task implements Future RunnableFuture interface, and Future RunnableFuture interface extends Runnable interface, passing in a Task would be equivalent to calling this overload. This overload does not expect a result to be returned, because Runnable is something that you run without a result. Calling get() on the Future returned by this overload will block until the task finishes, and null will be returned. If you need to retrieve the value returned by the Task, you need to call get() of the Task, not the Future returned by ExecutorService.submit().
Edit based on OP's comments
Firstly, since the calling method is already running in a background thread, and all tasks are expected to run sequentially (instead of parallelly), then you should just run them without all these additional ExecutorService and Task, unless there is another reason why this has to be done.
Secondly, a List object is nothing but an object doing referencing. What could have really affected performance is that you are copying the reference of the elements to the new list. You could have used List.subList()if the indices are known, as the returned list would use the same backing array as the original list, so there isn't an additional O(n) operation for copying.
What's the prefered method to access the underlying Callable after a CancellationException exception of a FutureTask.get?
I have the following code -
public class Ping implements Callable
{
public Ping(String serverName)
{
// stuff
}
// call() method, etc.
}
// other code
futures = executor.invokeAll(callables, TIMEOUT_SECONDS, TimeUnit.SECONDS);
for (Future<Object> future : futures)
{
try
{
PingStatus status = (PingStatus)future.get();
// do stuff
}
catch (CancellationException e)
{
// HELP: throw new RuntimeException("Could not ping " + callable.serverName);
}
}
If the timeout is reached, and a CancellationException is throwing on the get, I'd like to throw a new exception that includes the serverName passed into the Callable. What's the best pattern here? And, why doesn't FutureTask provide a reference to the underlying Callable passed in on the constructor?
The original Callable is not retrievable from the Future object due to the separation between the task and the result. There are many methods which would result in Future objects being returned that do not involve the use or creation of Callable objects. Take for instance the method submit(Runnable task) which takes a runnable instead.
Runnable and Callable do not share a common parent superclass meaning that if the future object were to give you the ability to retrieve it, it would have to return an object of type Object. And that is just plain ugly.
Fortunately, if you have read the documentation for the returned list in invokeAll() (emphasis mine):
a list of Futures representing the tasks, in the same sequential order as produced by the iterator for the given task list.
meaning that the order of the input collection of Callable to the returned list of Future is preserved. By this, you can use the current index of Future to work out which Callable was cancelled.
E.g:
futures = executor.invokeAll(callables, TIMEOUT_SECONDS, TimeUnit.SECONDS);
int index = 0; // Index used for for-loop
for (Future<Object> future : futures){
try{
PingStatus status = (PingStatus)future.get();
// do stuff
}catch(CancellationException e){
Callable<Object> offendingCallable = callables.get(index);
// deal with object here
}
index++;
}
As a side note, it seems like you are returning an object PingStatus as a result from the execution. You should thus declare your custom callable as:
public class Ping<PingStatus> implements Callable{
and your appropriate future objects as Future<PingStatus> to avoid nasty casts from Object to PingStatus.
Is there an ExecutorService that will allow me to submit tasks without beginning execution until I request it? I'm looking for something like ScheduledExecutorService, except that I want to trigger the execution manually without depending on a fixed time delay.
The reason I'm looking for this is because I want to create a set of tasks which may recursively use results of Futures generated from parallel tasks in the same set. So I would need to first submit all the tasks in order to get a set of Futures, and only then could I allow the tasks to begin executing.
It sounds like a job for CompletableFuture
fire execution of first portion of tasks as separe CompletableFutures
then using CompletableFuture.allOf(...furures) to create a barrier future that completes only when all are done
then using one of combinators like CompletableFuture.thenAccept to schedule next portion of tasks to perform on completion of barrier future
But more idiomatic way to use it would be to chain each next task based on future result of some previous one
CompletableFuture<FirstResult> firstTask = //....
CompletableFuture<SecondResult> secondTask = firstTask.thenApply(someTransformation);
CompletableFuture<Void> anotherTaks = firstTask.thenAccept(someConsumer);
CompletableFuture<ThirdResult> combined = firstTask.thenAcceptBoth(secondTask, someFunction);
Perhaps an alternate approach would be to simply use a FutureCallback or an AsyncFunction?
FutureCallback example:
final List<ListenableFuture<T>> futures = new ArrayList<ListenableFuture<T>>();
final Callable<T> callable = new Callable<T>() {
// Some task you want to complete
};
// Submit all your tasks for execution
futures.add(listeningExecutorService.submit(callable));
// ... add as many tasks as you have
futures.add(listeningExecutorService.submit(callable));
// Get a single Future to wait on
final ListenableFuture<List<T>> future = Futures.allAsList(futures);
Futures.addCallback(future, new FutureCallback<List<T>>() {
#Override
public void onSuccess(final List<T> result) {
// Begin other tasks using `result` (the set of results from the first tasks)
}
#Override
public void onFailure(final Throwable t) {
// ...
}
});
This would be helpful if you don't care about waiting around for the second set of tasks to complete, as Futures.addCallback doesn't return anything.
AsyncFunction example:
final ListenableFuture<O> result = Futures.transform(future, new AsyncFunction<List<T>, O>() {
#Override
public ListenableFuture<O> apply(final List<T> input) {
// Begin other tasks using `input` (the set of results from the first tasks)
}
});
This would be beneficial if you want to wait on the resulting ListenableFuture, or potentially add a third set of tasks that need to happen upon completion of the second set.