How to execute a CompletableFuture asynchronously - java

I have created a method that implements an async retry pattern. Actually, I want that when I call this method request should process in a separate thread and it should retry with some delay
private <R> CompletableFuture<R> withRetryRequest(Supplier<CompletableFuture<R>> supplier, int maxRetries) {
CompletableFuture<R> f = supplier.get();
for (int i = 0; i < maxRetries; i++) {
f = f.thenApply(CompletableFuture::completedFuture)
.exceptionally(t -> {
try {
Thread.sleep(10 * 1000);
} catch (Exception exp) {
log.log(Level.SEVERE, "Error while delay executing", exp);
}
return supplier.get();
})
.thenCompose(Function.identity());
}
return f;
}
here is a caller part:
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(PropUtil.getPropUtil().THREAD_POOL_SIZE);
CompletableFuture<Boolean> retry = this.withRetryRequest(() -> runDoorOpenProcedure(req), req.getRetryCount());
final CompletableFuture<Boolean> retryFinal = retry;
CompletableFuture<CompletableFuture<Boolean>> retryRes = CompletableFuture.supplyAsync(() -> retryFinal, executor);
Boolean success = retry.get().join();
But it seems that call is not async at all. What I am doing wrong here, Can someone please have a look into this?

check this: https://winterbe.com/posts/2015/04/07/java8-concurrency-tutorial-thread-executor-examples/
CompletedFuture is suitable for some scenarios, such as you want to split your tasks into parallel and you still need the task result to continue or aggregate, then your main thread waits until you get all the results from all the subTasks. The main thread is blocked when subTasks are running.
If you don't need the results of the async tasks, you could create Thread and throw them into ThreadPool, then return.

Related

Retrieve the instance of runnable from completablefuture

I am running a list of runnables using ExecutorService and collating all results using CompletableFuture. I would like to correlate which instance of CompletableFuture ran a specific runnable.
Here is the actual code
public static void runTasks(final List<Runnable> tasks, final int threadCount) {
final ExecutorService es = Executors.newFixedThreadPool(threadCount);
final CompletableFuture<?>[] futures = tasks.stream()
.map(task -> CompletableFuture.runAsync(task, es))
.toArray(CompletableFuture[]::new);
try {
CompletableFuture.allOf(futures).join();
es.shutdown();
} catch (Exception e) {
System.exit(1);
}
}
I have the results stored in futures variable
CompletableFuture<?>[] futures
Is there a way to get the class name of runnable whose result is stored in an instance of future?
I am trying to print the individual task result as follows:
for (CompletableFuture future : futures) {
final boolean taskCompletedSuccessfully = future.isDone() && !(future.isCompletedExceptionally() || future.isCancelled());
LOGGER.info("Task completion status for {} : {}", <runnable class name>, (taskCompletedSuccessfully ? "SUCCESSFUL" : "FAILED"));
}
It is not possible to retrieve any information about the Runnable because the CompletableFuture does not hold any reference to it.
You will thus have to store the future and the runnable (or its class name) together in some Pair implementation, e.g.:
final List<Pair<Runnable, CompletableFuture<Void>>> futures = tasks.stream()
.map(task -> new Pair<>(task, CompletableFuture.runAsync(task, es)))
.collect(toList());
try {
CompletableFuture.allOf(futures.stream().map(Pair::getB).toArray(CompletableFuture[]::new)).join();
} catch (Exception e) {
log.warn("At least one future failed", e);
}
es.shutdown();
futures.forEach(pair -> {
CompletableFuture<Void> future = pair.getB();
final boolean taskCompletedSuccessfully = !future.isCompletedExceptionally();
log.info("Task completion status for {} : {}", pair.getA().getClass().getSimpleName(), (taskCompletedSuccessfully ? "SUCCESSFUL" : "FAILED"));
});
A few notes:
if any of the tasks fails, the allOf() will fail as well. You probably don't want to exit() in that case – otherwise you will always have only successful tasks logged;
after allOf().join(), you are guaranteed that isDone() holds true for all tasks, no need to check it;
isCancelled() (which is not possible here) implies isCompletedExceptionally()

Does orTimeout method of CompletableFuture on Java-9 kill the long running task? [duplicate]

I have method that is checking the CompletableFuture execution time. If such CompletableFuture is executing for more than 2 seconds i want to kill this task. But how can I doit if i don't have control overy thread where CompletableFuture methods are executed ?
final CompletableFuture<List<List<Student>>> responseFuture = new CompletableFuture<>();
responseFuture.supplyAsync(this::createAllRandomGroups)
.thenAccept(this::printGroups)
.exceptionally(throwable -> {
throwable.printStackTrace();
return null;
});
createAllRandomGroups()
private List<List<Student>> createAllRandomGroups() {
System.out.println("XD");
List<Student> allStudents = ClassGroupUtils.getActiveUsers();
Controller controller = Controller.getInstance();
List<List<Student>> groups = new ArrayList<>();
int groupSize = Integer.valueOf(controller.getGroupSizeComboBox().getSelectionModel().getSelectedItem());
int numberOfGroupsToGenerate = allStudents.size() / groupSize;
int studentWithoutGroup = allStudents.size() % groupSize;
if (studentWithoutGroup != 0) groups.add(this.getListOfStudentsWithoutGroup(allStudents, groupSize));
for(int i = 0; i < numberOfGroupsToGenerate; i++) {
boolean isGroupCreated = false;
while (!isGroupCreated){
Collections.shuffle(allStudents);
List<Student> newGroup = this.createNewRandomGroupOfStudents(allStudents, groupSize);
groups.add(newGroup);
if (!DataManager.isNewGroupDuplicated(newGroup.toString())) {
isGroupCreated = true;
allStudents.removeAll(newGroup);
}
}
}
DataManager.saveGroupsToCache(groups);
return groups;
}
printGroups()
private void printGroups(List<List<Student>> lists) {
System.out.println(lists);
}
This statement responseFuture.cancel(true); does not kill thread where responseFuture is doing the methods. So what is the most elegant way to terminate CompletableFuture thread ?
When you create a chain of CompletableFuture stages like b = a.thenApply(function), this handy method creates a setup of different components. Basically, these components refer to each other as a → function → b, so the completion of a will trigger the evaluation of function which will first pre-check whether b still is not completed, then evaluate your function and attempt to complete b with the result.
But b itself has no knowledge of function or the thread that will evaluate it. In fact, function is not special to b, anyone could call complete, completeExceptionally or cancel on it from any thread, the first one winning. Hence, the completable in the class name.
The only way to get hands on the threads evaluating the functions, is to be in control of them right from the start, e.g.
ExecutorService myWorkers = Executors.newFixedThreadPool(2);
CompletableFuture<FinalResultType> future
= CompletableFuture.supplyAsync(() -> generateInitialValue(), myWorkers)
.thenApplyAsync(v -> nextCalculation(v), myWorkers)
.thenApplyAsync(v -> lastCalculation(v), myWorkers);
future.whenComplete((x,y) -> myWorkers.shutdownNow());
Now, the completion of future, e.g. via cancellation, will ensure that no new evaluation will be triggered by this chain and further makes an attempt to interrupt ongoing evaluations, if any.
So you can implement a timeout, e.g.
try {
try {
FinalResultType result = future.get(2, TimeUnit.SECONDS);
System.out.println("got "+result);
}
catch(TimeoutException ex) {
if(future.cancel(true)) System.out.println("cancelled");
else System.out.println("got "+future.get());
}
}
catch(ExecutionException|InterruptedException ex) {
ex.printStackTrace();
}
Not that the rejection of tasks due to the shutdown of the thread pool may cause some of the intermediate future to never complete, but for this chain of stages, this is irrelevant. All that matters, is, that the final stage future is completed, which is guaranteed, as it is its completion which triggers the shutdown.
The only way to terminate a thread is via interruption, which is a cooperative mechanism. This means the the thread must implement interruption logic, by handling the InterruptedException.
But it is a really bad practice to interrupt threads that you don't own, which I think is your case.

How to kill CompletableFuture related threads?

I have method that is checking the CompletableFuture execution time. If such CompletableFuture is executing for more than 2 seconds i want to kill this task. But how can I doit if i don't have control overy thread where CompletableFuture methods are executed ?
final CompletableFuture<List<List<Student>>> responseFuture = new CompletableFuture<>();
responseFuture.supplyAsync(this::createAllRandomGroups)
.thenAccept(this::printGroups)
.exceptionally(throwable -> {
throwable.printStackTrace();
return null;
});
createAllRandomGroups()
private List<List<Student>> createAllRandomGroups() {
System.out.println("XD");
List<Student> allStudents = ClassGroupUtils.getActiveUsers();
Controller controller = Controller.getInstance();
List<List<Student>> groups = new ArrayList<>();
int groupSize = Integer.valueOf(controller.getGroupSizeComboBox().getSelectionModel().getSelectedItem());
int numberOfGroupsToGenerate = allStudents.size() / groupSize;
int studentWithoutGroup = allStudents.size() % groupSize;
if (studentWithoutGroup != 0) groups.add(this.getListOfStudentsWithoutGroup(allStudents, groupSize));
for(int i = 0; i < numberOfGroupsToGenerate; i++) {
boolean isGroupCreated = false;
while (!isGroupCreated){
Collections.shuffle(allStudents);
List<Student> newGroup = this.createNewRandomGroupOfStudents(allStudents, groupSize);
groups.add(newGroup);
if (!DataManager.isNewGroupDuplicated(newGroup.toString())) {
isGroupCreated = true;
allStudents.removeAll(newGroup);
}
}
}
DataManager.saveGroupsToCache(groups);
return groups;
}
printGroups()
private void printGroups(List<List<Student>> lists) {
System.out.println(lists);
}
This statement responseFuture.cancel(true); does not kill thread where responseFuture is doing the methods. So what is the most elegant way to terminate CompletableFuture thread ?
When you create a chain of CompletableFuture stages like b = a.thenApply(function), this handy method creates a setup of different components. Basically, these components refer to each other as a → function → b, so the completion of a will trigger the evaluation of function which will first pre-check whether b still is not completed, then evaluate your function and attempt to complete b with the result.
But b itself has no knowledge of function or the thread that will evaluate it. In fact, function is not special to b, anyone could call complete, completeExceptionally or cancel on it from any thread, the first one winning. Hence, the completable in the class name.
The only way to get hands on the threads evaluating the functions, is to be in control of them right from the start, e.g.
ExecutorService myWorkers = Executors.newFixedThreadPool(2);
CompletableFuture<FinalResultType> future
= CompletableFuture.supplyAsync(() -> generateInitialValue(), myWorkers)
.thenApplyAsync(v -> nextCalculation(v), myWorkers)
.thenApplyAsync(v -> lastCalculation(v), myWorkers);
future.whenComplete((x,y) -> myWorkers.shutdownNow());
Now, the completion of future, e.g. via cancellation, will ensure that no new evaluation will be triggered by this chain and further makes an attempt to interrupt ongoing evaluations, if any.
So you can implement a timeout, e.g.
try {
try {
FinalResultType result = future.get(2, TimeUnit.SECONDS);
System.out.println("got "+result);
}
catch(TimeoutException ex) {
if(future.cancel(true)) System.out.println("cancelled");
else System.out.println("got "+future.get());
}
}
catch(ExecutionException|InterruptedException ex) {
ex.printStackTrace();
}
Not that the rejection of tasks due to the shutdown of the thread pool may cause some of the intermediate future to never complete, but for this chain of stages, this is irrelevant. All that matters, is, that the final stage future is completed, which is guaranteed, as it is its completion which triggers the shutdown.
The only way to terminate a thread is via interruption, which is a cooperative mechanism. This means the the thread must implement interruption logic, by handling the InterruptedException.
But it is a really bad practice to interrupt threads that you don't own, which I think is your case.

is invokeAll() a blocking call in java 7

ExecutorService executorService = Executors.newSingleThreadExecutor();
Set<Callable<String>> callables = new HashSet<Callable<String>>();
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 1";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 2";
}
});
callables.add(new Callable<String>() {
public String call() throws Exception {
return "Task 3";
}
});
List<Future<String>> futures = executorService.invokeAll(callables);
for(Future<String> future : futures){
System.out.println("future.get = " + future.get());
}
For this code piece. My question is "is invokeAll() a blocking call "?
I mean, when code ran to invokeAll() line, are we bloking there to wait for all result been generated?
Executes the given tasks, returning a list of Futures holding their
status and results when all complete. Future.isDone() is true for each
element of the returned list. Note that a completed task could have
terminated either normally or by throwing an exception. The results of
this method are undefined if the given collection is modified while
this operation is in progress.
Futures can only be done when execution is finished, therefore this method can only return when the tasks have been executed.
That it can throw an InterruptedException is also indicative of a blocking action.
Looking at the implementation of invokeAll in java.util.concurrent.AbstractExecutorService (comment inline):
// from OpenJDK source; GPL-2.0-with-classpath-exception
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks) {
RunnableFuture<T> f = newTaskFor(t);
futures.add(f);
execute(f);
}
for (int i = 0, size = futures.size(); i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
try {
f.get(); // <== *** BLOCKS HERE ***
} catch (CancellationException ignore) {
} catch (ExecutionException ignore) {
}
}
}
done = true;
return futures;
} finally {
if (!done)
for (int i = 0, size = futures.size(); i < size; i++)
futures.get(i).cancel(true);
}
}
In fact, looking at a reference implementation is what you generally should do in these cases when the Javadoc-Specese appears to be difficult to decipher. (with the caveat in mind that some implementation details are not part of the spec.)
You mean if the parent thread will wait for all the thread created using your ExecutorService invocation? Then answer is yes, parent thread will wait and once all threads are finished you will get the list of Futures object which will hold the result of each thread execution.
See below from ExecutorService.invokeAll()
Executes the given tasks, returning a list of Futures holding their
status and results when all complete.
InvokeAll method blocks till all the tasks are completed and list of futures are returned,
Solution:
If we don't want this to happen and continue with execution of program ,we can Loop through the tasks and pass it to Submit method of ExecutorService and add it to the List of Future Objects
ExecutorService es=Executors.newFixedThreadPool(4);
List<SampleClassimplementingCallable<String>> tasks=new ArrayList<>();
List<Future<String>> futures=new ArrayList<>();
for(SampleClassimplementingCallable<String> s:tasks)
{
//This Won't Block the Calling Thread and We will get the list of futures
futures.add(es.submit(s));
}
However, When the Futures are retrieved from the list and get method is called on indivual future object ,then the thread is blocked.

Parallel execution of callables

I'd like to execute multiple callables parallel. But it seems that the ExecutorService always waits until all callables are finnished.
I've tried the following:
final int nThreads = 10;
ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
List<PrimeCallable> tasks = new ArrayList<PrimeCallable>();
for(int i = 0; i < nThreads; i++) {
tasks.add(new PrimeCallable(0, i * 100 + 100, "thread" + i));
}
try {
for(Future<List<Integer>> result : executorService.invokeAll(tasks)) {
List<Integer> integers = result.get();
for(Integer i : integers){
System.out.println(i);
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Now, the for loop is called when all callables in the executorService are finnished. As far as I know, there is no executorService.isParallel setter ;-).
What would be the right approach to let callables run parallel?
Thanks for your hints!
The javadocs for invokeAll says;
Executes the given tasks, returning a
list of Futures holding their status
and results when all complete. Future.isDone() is true for each element of the returned list.
So invokeAll blocks until each task in the collection is complete.
Executor service runs all your callables in parallel. All it does is , it waits for all parallel tasks to complete before it moves on. So its not like where all the tasks are run in serial.
It sounds like part of what you want is lazy execution - you don't want to have to make a copy of the structure in memory before extracting results.
I would treat this as an iteration + transformation problem. First, define an iterator over your input, such that each call to next() returns a Callable that will produce the next value in your series.
The transform stage is to apply a parallel or concurrent evaluation of those Callables, something like this (not tested):
public class ConcurrentTransform
{
private final ExecutorService executor;
private final int maxBuffer;
public ConcurrentTransform(ExecutorService executor, int maxWorkBuffer) {
this.executor = executor;
this.maxBuffer = Math.max(1, maxWorkBuffer);
}
public <T> Iterator<T> apply(final Iterator<Callable<T>> input) {
// track submitted work
final BlockingQueue<Future<T>> submitted = new LinkedBlockingQueue<Future<T>>();
// submit first N tasks
for (int i=0; i<maxBuffer && input.hasNext(); i++) {
Callable<T> task = input.next();
Future<T> future = executor.submit(task);
submitted.add(future);
}
return new Iterator<T>(){
#Override
public synchronized boolean hasNext() {
return !submitted.isEmpty();
}
#Override
public T next() {
Future<T> result;
synchronized (this) {
result = submitted.poll();
if (input.hasNext()) {
submitted.add(executor.submit(input.next()));
}
}
if (result != null) {
try {
return result.get(); // blocking
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
throw new RuntimeException(e);
}
}
} else {
throw new NoSuchElementException();
}
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}};
}
}
After calling apply(...), you'd iterate over the resulting values, which under the covers would be executing the Callable objects in parallel and returning results in the same order as they were input. Some refinements would be to allow an optional timeout for the blocking result.get() call, or to manage the thread pool within the transform itself.
If you want to view results as they happen, use the ExecutorCompletionService.

Categories

Resources