Get all futures that finish within a set period of time? - java

I have a list of callables and I want to start them all in parallel, give them 5 seconds to complete, and use the results from any of the tasks that finish within that time.
I tried using executorService.invokeAll with a timeout, but in this case they all need to finish before my timeout.
What is the best way to do this using Java 7?

What I do is submit all the tasks and add the Futures to a list.
You can then wait for the timeout, and get all the Futures where isDone() is true.
Alternatively you can call get on each of the Futures which a decreasing timeout based on the amount of time remaining.

Just check after 5s if the Future is terminated using isDone:
List<Callable<V>> callables = // ...
ExecutorService es = Executors.newFixedThreadPool(callables.size()));
List<Future<V>> futures = es.invokeAll(callables);
// Wait 5s
Thread.sleep(5000);
List<V> terminatedResults = new ArrayList<>();
for(Future<V> f : futures) {
if(f.isDone()) {
terminatedResults.add(f.get());
} else {
// cancel the future?
}
}
// use terminatedResults

Ok, the answers helped me get to the solution. The issue with Logeart's answer is that I want to give them a max time - so if they finish quicker, I get them all (sorry if this wasn't clear in the question).
The other issue is that isDone() does not catch the case when a task is cancelled - you need to use isCancelled(). So, my working solution was:
ExecutorService exectutorService = Executors.newCachedThreadPool();
List<Callable<Object>> callables = Arrays.asList(
(Callable(Object) new Check1Callable(),
(Callable(Object) new Check2Callable(),
(Callable(Object) new Check3Callable());
List<Future<Object>> futures = new ArrayList<>();
try {
futures = executorService.invokeAll(callables,maxWaitTime, TimeUnit.SECONDS);
} catch (Exception e) {
}
for (Future thisFuture : futures) {
try {
if (thisFuture.isDone() && !thisFuture.isCancelled()) {
<accept the future's result>
}
} catch (Exception e) {
}
}

Related

ScheduledFuture returns null when a task is submitted or scheduleAtFixedRate

I am trying to schedule a job to run every 10 minutes using ScheduledThreadPoolExecutor. There are 10 threads in the thread pool.
Code looks like:
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10, r -> {
Thread t = new Thread(r);
t.setName("thread");
return t;
}, (runnable, pool) -> {
});
List<ScheduledFuture<?>> listOfFutures = new ArrayList<>();
ScheduledFuture<?> future = executor.scheduleAtFixedRate(() -> {
try {
System.out.println("John is a good guy");
} catch (Exception e) {
// eat the exception
}
}, 0, 10, TimeUnit.MINUTES);
listOfFutures.add(future);
Now, if 100 tasks were scheduled and their future were added to a list.
When we try to iterate the list and do future.cancel(), out of 100, 2-3 futures turn out to be null.
What is the possible reason here?
I had to add an initial delay of 2 seconds in order to ensure that the future is not null. But I also have an ExecutorService with the same problem (future is null in few cases). But there is no delay that can be added there.
Most likely it is that the executor pool has been shutdown or encounted some issue. You've not implemented the RejectedExecutionHandler very clearly, it just discards errors so you have no idea when they occur.
You can get more information on when / how any executor service issue occurs if you drop the last parameter to new ScheduledThreadPoolExecutor to remove the pointless handler (runnable, pool) -> {}. This will instead use the default abort policy.
Alternatively change your rejected handler so that it tells you of the problem when there is one:
(runnable, pool) -> {
throw new RejectedExecutionException("*** FAILED ***"
+" isShutdown()="+pool.isShutdown()
+" getActiveCount()="+pool.getActiveCount()
+" queue size="+pool.getQueue().size());
}
When running with your original handler (runnable, pool) -> {} you will need to check each call as you otherwise will have no indication of when there is an issue:
ScheduledFuture<?> future = executor.scheduleAtFixedRate(() -> { ... }, 0, 10, TimeUnit.MINUTES);
if (future == null)
throw new RuntimeException("*** FAILED to add new action ***");

How to enforce timeout and cancel async CompletableFuture Jobs

I am using Java 8, and I want to know the recommended way to enforce timeout on 3 async jobs that I would to execute async and retrieve the result from the future. Note that the timeout is the same for all 3 jobs. I also want to cancel the job if it goes beyond time limit.
I am thinking something like this:
// Submit jobs async
List<CompletableFuture<String>> futures = submitJobs(); // Uses CompletableFuture.supplyAsync
List<CompletableFuture<Void>> all = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
try {
allFutures.get(100L, TimeUnit.MILLISECONDS);
} catch (TimeoutException e){
for(CompletableFuture f : future) {
if(!f.isDone()) {
/*
From Java Doc:
#param mayInterruptIfRunning this value has no effect in this
* implementation because interrupts are not used to control
* processing.
*/
f.cancel(true);
}
}
}
List<String> output = new ArrayList<>();
for(CompeletableFuture fu : futures) {
if(!fu.isCancelled()) { // Is this needed?
output.add(fu.join());
}
}
return output;
Will something like this work? Is there a better way?
How to cancel the future properly? Java doc says, thread cannot be interrupted? So, if I were to cancel a future, and call join(), will I get the result immediately since the thread will not be interrupted?
Is it recommended to use join() or get() to get the result after waiting is over?
It is worth noting that calling cancel on CompletableFuture is effectively the same as calling completeExceptionally on the current stage. The cancellation will not impact prior stages. With that said:
In principle, something like this will work assuming upstream cancellation is not necessary (from a pseudocode perspective, the above has syntax errors).
CompletableFuture cancellation will not interrupt the current thread. Cancellation will cause all downstream stages to be triggered immediately with a CancellationException (will short circuit the execution flow).
'join' and 'get' are effectively the same in the case where the caller is willing to wait indefinitely. Join handles wrapping the checked Exceptions for you. If the caller wants to timeout, get will be needed.
Including a segment to illustrate the behavior on cancellation. Note how downstream processes will not be started, but upstream processes continue even after cancellation.
public static void main(String[] args) throws Exception
{
int maxSleepTime = 1000;
Random random = new Random();
AtomicInteger value = new AtomicInteger();
List<String> calculatedValues = new ArrayList<>();
Supplier<String> process = () -> { try { Thread.sleep(random.nextInt(maxSleepTime)); System.out.println("Stage 1 Running!"); } catch (InterruptedException e) { e.printStackTrace(); } return Integer.toString(value.getAndIncrement()); };
List<CompletableFuture<String>> stage1 = IntStream.range(0, 10).mapToObj(val -> CompletableFuture.supplyAsync(process)).collect(Collectors.toList());
List<CompletableFuture<String>> stage2 = stage1.stream().map(Test::appendNumber).collect(Collectors.toList());
List<CompletableFuture<String>> stage3 = stage2.stream().map(Test::printIfCancelled).collect(Collectors.toList());
CompletableFuture<Void> awaitAll = CompletableFuture.allOf(stage2.toArray(new CompletableFuture[0]));
try
{
/*Wait 1/2 the time, some should be complete. Some not complete -> TimeoutException*/
awaitAll.get(maxSleepTime / 2, TimeUnit.MILLISECONDS);
}
catch(TimeoutException ex)
{
for(CompletableFuture<String> toCancel : stage2)
{
boolean irrelevantValue = false;
if(!toCancel.isDone())
toCancel.cancel(irrelevantValue);
else
calculatedValues.add(toCancel.join());
}
}
System.out.println("All futures Cancelled! But some Stage 1's may still continue printing anyways.");
System.out.println("Values returned as of cancellation: " + calculatedValues);
Thread.sleep(maxSleepTime);
}
private static CompletableFuture<String> appendNumber(CompletableFuture<String> baseFuture)
{
return baseFuture.thenApply(val -> { System.out.println("Stage 2 Running"); return "#" + val; });
}
private static CompletableFuture<String> printIfCancelled(CompletableFuture<String> baseFuture)
{
return baseFuture.thenApply(val -> { System.out.println("Stage 3 Running!"); return val; }).exceptionally(ex -> { System.out.println("Stage 3 Cancelled!"); return ex.getMessage(); });
}
If it is necessary to cancel the upstream process (ex: cancel some network call), custom handling will be needed.
After calling cancel you cannot join the furure, since you get an exception.
One way to terminate the computation is to let it have a reference to the future and check it periodically: if it was cancelled abort the computation from inside.
This can be done if the computaion is a loop where at each iteration you can do the check.
Do you need it to be a CompletableFuture? Cause another way is to avoid to use a CompleatableFuture, and use a simple Future or a FutureTask instead: if you execute it with an Executor calling future.cancel(true) will terminate the computation if possbile.
Answerring to the question: "call join(), will I get the result immediately".
No you will not get it immediately, it will hang and wait to complete the computation: there is no way to force a computation that takes a long time to complete in a shorter time.
You can call future.complete(value) providing a value to be used as default result by other threads that have a reference to that future.

Parallellize a for loop in Java using multi-threading

I am very new to java and I want to parallelize a nested for loop using executor service or using any other method in java. I want to create some fixed number of threads so that CPU is not completely acquired by threads.
for(SellerNames sellerNames : sellerDataList) {
for(String selleName : sellerNames) {
//getSellerAddress(sellerName)
//parallize this task
}
}
size of sellerDataList = 1000 and size of sellerNames = 5000.
Now I want to create 10 threads and assign equal chunk of task to each thread equally. That is for i'th sellerDataList, first thread should get address for 500 names, second thread should get address for next 500 names and so on.
What is the best way to do this job?
There are two ways to make it run parallelly: Streams and Executors.
Using streams
You can use parallel streams and leave the rest to the jvm. In this case you don't have too much control over what happens when. On the other hand your code will be easy to read and maintain:
sellerDataList.stream().forEach(sellerNames -> {
Stream<String> stream = StreamSupport.stream(sellerNames.spliterator(), true); // true means use parallel stream
stream.forEach(sellerName -> {
getSellerAddress(sellerName);
});
});
Using an ExecutorService
Suppose, you want 5 Threads and you want to be able to wait until task completion. Then you can use a fixed thread pool with 5 threads and use Future-s so you can wait until they are done.
final ExecutorService executor = Executors.newFixedThreadPool(5); // it's just an arbitrary number
final List<Future<?>> futures = new ArrayList<>();
for (SellerNames sellerNames : sellerDataList) {
for (final String sellerName : sellerNames) {
Future<?> future = executor.submit(() -> {
getSellerAddress(sellerName);
});
futures.add(future);
}
}
try {
for (Future<?> future : futures) {
future.get(); // do anything you need, e.g. isDone(), ...
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
If you are using a parallel stream you can still control the thread by creating your own ForkJoinPool.
List<Long> aList = LongStream.rangeClosed(firstNum, lastNum).boxed()
.collect(Collectors.toList());
ForkJoinPool customThreadPool = new ForkJoinPool(4);
long actualTotal = customThreadPool.submit(
() -> aList.parallelStream().reduce(0L, Long::sum)).get();
Here on this site, it is described very well.
https://www.baeldung.com/java-8-parallel-streams-custom-threadpool

Time out by which search method returns otherwise it will throw time out message

I want execute a search method by java main and want to implement the
Time out by which search method returns otherwise it will throw a time out message.
How can I achieve this time out functionality using thread or timer class?
One approach would be to submit your search task to an executor, and call get(timeout); on the returned future - in essence:
create a Callable with your task
run it with a timeout
if it times out, cancel it - for the cancellation to work, your Callable needs to react to an interruption
Callable<SearchResult> task = ...;
ExecutorService executor = Executors.newFixedThreadPool(1);
Future<SearchResult> f = executor.submit(task);
SearchResult result = null;
try {
result = f.get(2, TimeUnit.SECONDS); //2 seconds timeout
return result;
} catch (TimeOutException e) {
//handle the timeout, for example:
System.out.println("The task took too long");
} finally {
executor.shutdownNow(); //interrupts the task if it is still running
}

Java: ExecutorService with Callables: invokeAll() and future.get() - results in correct order?

Im using the ExecutorService in Java to invoke Threads with invokeAll(). After, I get the result set with future.get(). Its really important that I receive the results in the same order I created the threads.
Here is a snippet:
try {
final List threads = new ArrayList();
// create threads
for (String name : collection)
{
final CallObject object = new CallObject(name);
threads.add(object);
}
// start all Threads
results = pool.invokeAll(threads, 3, TimeUnit.SECONDS);
for (Future<String> future : results)
{
try
{
// this method blocks until it receives the result, unless there is a
// timeout set.
final String rs = future.get();
if (future.isDone())
{
// if future.isDone() = true, a timeout did not occur.
// do something
}
else
{
// timeout
// log it and do something
break;
}
}
catch (Exception e)
{
}
}
}
catch (InterruptedException ex)
{
}
Is it assured that I receive the results from future.get() in the same order I created new CallObjects and added them to my ArrayList? I know, Documentation says the following:
invokeAll(): returns a list of Futures representing the tasks, in the same sequential order as produced by the iterator for the given task list. If the operation did not time out, each task will have completed. If it did time out, some of these tasks will not have completed. But I wanted to make sure I understood it correctly....
Thanks for answers! :-)
This is exactly what this piece of the statement is saying:
returns a list of Futures representing the tasks, in the same
sequential order as produced by the iterator for the given task list.
You will get the Futures in the exact order in which you inserted the items in the original list of Callables.
As per the documentation you will get the futures in same order.
Future object is just a reference of the task.
Future#get() is blocking call.
For ex
We have submitted 4 tasks.
Task 1 - > Completed
Task 2 --> Completed
Task 3 --> Timed Out
Task 4 --> Completed
As per our code
for (Future future : futures) {
future.get(); }
For 1&2 second task it will return immediately. We will wait for the third task will get completed. Even 4th task completed , iteration is waiting in third task . Once third task completed or timed wait expire on that time only iteration will continue.

Categories