2

In my project, there is a method with return type List of Future. This other developer has iterated over for loop as such

public List<Future<Object>> method1(){
    List<Future<Object>> lists = new ArrayList();
    for(MultipartFile file : files){
      Future<Object> future = service.method2(file);
      lists.add(future);
    }
   return lists;
}

Now i have to perform certain operations on Object of a list as soon as it is processed. How i do this? Even if i put a for loop like

for(Future<Object> future : lists){
  if(future.isDone()){
       performOtherOperation(future.get());
  }
}

If first object is not processed, the isDone() condition will fail and it will be ignored and 2nd iteration will start, how can i process this?

Can this be also done using ExecutorService?? i am not familiar with ExecutorService.

Edit : So i edited the method2(File) of service class from

public Future<Object> method2(File){
  object = operation();
  return new AsyncResult(object);
}

to public CompletableFuture method2(File);

But what is the return type i should choose which is equivalent to AsyncResult. AsyncResult is an implementation of Spring framework.

I can't modify this code until i am 100% sure it will not break existing multithreading performance or degrade it.

Asif Ansari
  • 93
  • 1
  • 7

1 Answers1

2

If you can change service.method2 to return a CompletableFuture, then the problem becomes trivial:

for(CompletableFuture<Object> future : lists){
  future.whenComplete((obj, err) -> performOtherOperation(obj));
}

If you absolutely can't modify method2, then you could convert the Future objects to CompletableFutures as described in Transform Java Future into a CompletableFuture

MikeFHay
  • 8,562
  • 4
  • 31
  • 52
  • I have two doubts 1) Does Future callback in the list too, i know list carries a reference of object. But not sure, if the callback happens too if Future is populated outside list? 2) Is whenComplete() async or it will block the iteration? – Asif Ansari Jul 24 '19 at 15:33
  • Is there any other option other than "List" for return type for either Future or CompletableFuture? – Asif Ansari Jul 24 '19 at 15:35
  • 1. If you call `whenComplete` on a CompletableFuture, the callback function will be called as soon as the future completes, no matter where the future is stored or which thread completes it. – MikeFHay Jul 24 '19 at 15:47
  • 2) `whenComplete` never blocks awaiting completion of the future. However if the future is already complete when `whenComplete` is called, then the callback will be executed synchronously in the calling thread. If that is undesirable then you can use `whenCompleteAsync` https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/CompletionStage.html#whenCompleteAsync(java.util.function.BiConsumer) – MikeFHay Jul 24 '19 at 15:48
  • 3) Both `Future` and `CompletableFuture` are capable of holding any type that extends Object (so basically anything), not just `List`. I recommend reading the docs: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/CompletableFuture.html https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/CompletionStage.html https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/Future.html – MikeFHay Jul 24 '19 at 15:49
  • Ok, how do I replace "return new AsyncResult(object)" for CompletableFuture? AsyncResult is spring implementation. – Asif Ansari Jul 24 '19 at 16:29
  • @AsifAnsari just call [completable()](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/AsyncResult.html#completable--) – MikeFHay Jul 24 '19 at 17:56