Catching Exceptions of all Futures/Callables in an ExecutorService - java

I have an ExecutorService containing a number of running Callables. I have a list of Futures for these Callables. I want to find out as soon as possible if one of the Callables throws an Exception. All Callables are equally likely to throw an Exception. The Callables usually run for several hours.
The usual approach seems to be to use the Future.get() method. However, you can only use this for one Future. If another Future throws an Exception I am not notified. So I was thinking of writing a loop that checks the Future.isDone() method for all Futures and sleeping for some time after each iteration. However, this approach is not really nice, so I was wondering if there is a better way of doing this?

You should use an ExecutorCompletionService, wrap your executor with it and then calling #take() will return the first completed result.
Example:
CompletionService<Object> completionService = new ExecutorCompletionService<>(executor);
//submit a bunch of tasks
IntStream.range(0, 100).forEach(i-> completionService.submit(Object::new));
//Wait for any of them to complete, wrap in a loop to take them all
completionService.take();

You can use CompletableFuture for your use-case
static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)
Returns a new CompletableFuture that is completed when any of the
given CompletableFutures complete, with the same result. Otherwise, if
it completed exceptionally, the returned CompletableFuture also does
so, with a CompletionException holding this exception as its cause.
If no CompletableFutures are provided, returns an incomplete
CompletableFuture.
You should store all your futures in a list. `
Now
List<CompletableFuture<?>> futureList = // all futures;
while(futureList.size()>0){
CompletableFuture<?> completed = CompletableFuture.anyOf(futureList); //convert futureList to array
if(completed.isCompletedExceptionally()){
// first future that completed with an exception
}else{
//future completed without exception, store the result or process
futureList.remove(completed); // remove it from the incomplete list
}
}
You may obtain a CompletableFuture like
final CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//...long running...
return "returnVal";
},
executor); //here executor is your executor pool
If you don't want to use explicit executor pool
final CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//...long running...
return "returnVal";
});
However, in this case it will be submitted to the ForkJoinPool.commonPool()

Related

How to timeout a Future in Java without using Future.get() as it's a blocking operation?

I have a list of futures over which i keep looping checking Future.isDone() and if yes, then i use Future.get(). But, there are cases where the thread goes on forever and to avoid this i want to timeout.
Please help me timing out a future without using Future.get() as its a blocking operation. Most of the questions on timing out here on stackoverflow point to Future.get() with a timeout inside it.
If you can use CompletableFuture instead of plain Future you can use CompletableFuture.anyOf() method:
Returns a new CompletableFuture that is completed when any of the given CompletableFutures complete, with the same result.
CompletableFuture<Void> combinedFuture =
CompletableFuture.anyOf(future1, future2, future3);
combinedFuture.get();
if (future1.isDone()) { ... }
if (future2.isDone()) { ... }
if (future3.isDone()) { ... }
In Java 9 you have extra methods for handling timeouts e.g. CompletableFuture.completeOnTimeout().

Java CompletableFuture assigning executor

I am having confusion with defining executor in CompletableFuture. I am not sure how to tell CompletableFuture to run it in that particular executor. Thanks in advance.
//Suppose I have an executor
ExecutorService myExecutor=Executors.newFixedThreadPool(2);
//If I create a future like this
CompletableFuture.runAsync(() -> {
//Do something
}, myExecutor); // I can put the executor here and say the future to this executor
//But I do not know where to put executor if I create my future in method style like this
private final CompletableFuture<Void> myMethod(String something) {
//Do something
return null;
}
//and use it like this
.thenCompose(this::myMethod); //How can I specify the executor in this case?
In your example, you have 3 CompletableFutures that are at play:
the one returned by runAsync()
the one returned by myMethod()
the one returned by thenCompose()
You also have 4 tasks that need to be run:
the one passed to runAsync() will be executed on the given executor and handle future 1;
the one that calls myMethod() from thenCompose() to create future 2 can be run on any executor, use thenComposeAsync() to explicitly choose one;
the one that will complete future 2 returned by myMethod() – this will be controlled inside myMethod() itself;
the one that will complete future 3 returned by thenCompose() – this is handled internally and will depend on execution order (e.g. if myMethod() returns an already completed future, it will also complete the former).
As you can see, several tasks and executors are involved, but you can always control the executors used in dependent stages using *Async() variants. The only case where you don't really control it is the 4th case, but it is a cheap operation as long as dependent stages use the *Async() variants as well.
you can do something like this:
ExecutorService es = Executors.newFixedThreadPool(4);
List<Runnable> tasks = getTasks();
CompletableFuture<?>[] futures = tasks.stream()
.map(task -> CompletableFuture.runAsync(task, es))
.toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futures).join();
es.shutdown();

Thread join vs ExecutorService.awaitTermination

I have a group of threads which all need to be executed in parallel and I must wait on all of them to complete.
Should I use the plain old Thread or the ExecutorService ? for the ExecutorService.awaitTermination I must give a certain time that I'm willing to wait but for Thread.join I must not.
I don't do anything with the results that the threads give , I don't need any futures.
EDIT:
ExecutorService es = Executors.newFixedThreadPool(kThreads);
List<Callable<Void>> calls = new LinkedList<>();
container.forEach(
calls.add(() -> { //creating a thread/task
BufferedImage scaledBufferedImage=imageService.scale(...);
imageService.transferToAWS(...);
return null;
})
);
es.invokeAll(calls); //executes each task
es.shutdown(); //ensure that no new tasks will be accepted
es.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); //wait for all tasks to finish
return kLinksToTheScaledImages;
As you say, you don't need the Futures as such, but you can use them to await termination.
Since you're using Java 8, you can do this via
ExecutorService es = Executors.newFixedThreadPool(kThreads);
container.stream()
.map(d -> createRunnable(d)) // now you have Runnables
.map(es::submit) // now they're Futures
.forEach(Future::get); // get() will wait for futures to finish
EDIT:
I just realized that the stream will probably prevent the parallelism to begin with, so you need to collect them intermediately:
List<Future<?>> futures = container.stream()
.map(d -> createRunnable(d)) // now you have Runnables
.map(es::submit) // now they're Futures
.collect(Collectors.toList());
futures.forEach(Future::get);
Actually, I fully understand that people are confused about having to wait without the futures returning a value. IMO, it would make more sense to have each future return the link of the upload it creates:
String scaleAndUpload() {
BufferedImage scaledBufferedImage=imageService.scale(...);
imageService.transferToAWS(...);
return linkToUploadedImage;
}
So you would get something like
List<Future<?>> futures = container.stream()
.map(d -> scaleAndUpload()) // now you have Runnables
.map(es::submit) // now they're Futures
.collect(Collectors.toList());
return futures.stream()
.map(Future::get) // collect the link when the future is finished
.collect(Collectors.toList()); // create a list of them
go for the executor service. this gives you many other benefits on top of managing the thread termination (e.g. capacity scaling and separation of execution logic and the actual tasks)
With Executors you just do this.
ex.shutdown();
while (!ex.awaitTermination(1, TimeUnit.MINUTES)) {
}
Where ex is your ExecutorService. In the loop you can check if your threads are still alive or something like that.
Should I use the plain old Thread or the ExecutorService ?
Use ExecutorService
for the ExecutorService.awaitTermination I must give a certain time that I'm willing to wait but for Thread.join I must not.
You have to look into this post for proper shutdown of ExecutorService.
How to properly shutdown java ExecutorService
Few more alternatives have been quoted in this post:
wait until all threads finish their work in java
You can do while(!executor.isTerminated) {}. Then you don't have to say how long you are willing to wait.

How does CompletableFuture know that tasks are independent?

Imagine that we have the following dummy code:
CompletableFuture<BigInteger> cf1 = CompletableFuture.supplyAsync(() -> BigInteger.valueOf(2L));
CompletableFuture<BigInteger> cf2 = CompletableFuture.supplyAsync(() -> BigInteger.valueOf(3L));
cf1.thenCombine(cf2, (x, y) -> x.add(y)).thenAccept(System.out::println);
Does JVM know that cf1 and cf2 carry independent threads in this case? And what will change if threads will be dependent (for example, use one connection to database)?
More general, how does CompletableFuture synchronize threads?
A CompletableFuture has no relation to any thread. It is just a holder for a result retrieved asynchronously with methods to operate on that result.
The static supplyAsync and runAsync methods are just helper methods. The javadoc of supplyAsync states
Returns a new CompletableFuture that is asynchronously completed by a
task running in the ForkJoinPool.commonPool() with the value obtained
by calling the given Supplier.
This is more or less equivalent to
Supplier<R> sup = ...;
CompletableFuture<R> future = new CompletableFuture<R>();
ForkJoinPool.commonPool().submit(() -> {
try {
R result = sup.get();
future.complete(result);
} catch (Throwable e) {
future.completeExceptionally(e);
}
});
return future;
The CompletableFuture is returned, even allowing you to complete it before the task submitted to the pool.
More general, how does CompletableFuture synchronize threads?
It doesn't, since it doesn't know which threads are operating on it. This is further hinted at in the javadoc
Since (unlike FutureTask) this class has no direct control over the
computation that causes it to be completed, cancellation is treated as
just another form of exceptional completion. Method cancel has the
same effect as completeExceptionally(new CancellationException()).
Method isCompletedExceptionally() can be used to determine if a
CompletableFuture completed in any exceptional fashion.
CompletableFuture objects do not control processing.
I don't think that a CompletableFuture (CF) "synchronizes threads". It uses the executor you have provided or the common pool if you have not provided one.
When you call supplyAsync, the CF submits the various tasks to that pool which in turns manages the underlying threads to execute the tasks.
It doesn't know, nor does it try to synchronize anything. It is still the client's responsibility to properly synchronize access to mutable shared data.

ExecutorService awaitTermination method not performing as expected

I'm trying to write a process in Java that executes a series of tasks concurrently, waits for the tasks to be done, then tags the overall process as complete. Each task has its own information, including when the individual task is complete. I'm using an ExecutorService for the process, and have boiled down the essence of the process as follows:
List<Foo> foos = getFoos();
ExecutorService executorService = Executors.newFixedThreadPool(foos.size());
for (Foo foo : foos) {
executorService.execute(new MyRunnable(foo));
}
executorService.shutdown();
try {
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// log the error.
}
completeThisProcess();
Each of the MyRunnable objects has a run method that makes a webservice call, then writes the results of the call to the database, including the time the call completed. The completeThisProcess method simply writes the status of the whole process as complete along with the time the process completed.
The problem I'm having is that when I look in the database after the process has completed, the completeThisProcess method has apparently been able to execute before all of the MyRunnables have completed. I'm noticing that the times that are written from the completeThisProcess method are even occasionally upwards of 20-30 seconds before the last MyRunnable task has completed.
Is there anything there that is obviously wrong with the process I've written? Perhaps I'm not understanding the ExecutorService correctly, but I thought that the awaitTermination method should be ensuring that all of the MyRunnable instances have completed their run methods (assuming they complete without exception, of course), which would result in all the sub-tasks having completion times before the overall process's completion time.
If you want to wait for all the threads to return is then following method can be trusted.
Make your thread class implement Callable interface instead of Runnable (In case of Callable run method will return some value. Make it return threadName.
Create a list of Callable Objects and use invokeAll method which will wait for all threads to return. For the below code assume the thread class name to be MyCallable.
ExecutorService executorService = Executors.newFixedThreadPool(foos.size());
List<Callable> tasks = new ArrayList<>();
for (Foo foo : foos) {
tasks.add(new MyCallable(foo));
}
executorService.invokeAll(tasks);
invokeAll returns List of future objects if you want to make use of it.
OR
you can use CountDownLatch.
CountDownLatch cdl = new CountDownLatch(foo.size);
Make it count down in run method using cdl.countDown() method.
Use cdl.await after for loop and then it will wait untill cdl become zero.
Heading

Categories