简体   繁体   中英

Best way to use Future in java

I have a set of jobs which I am submitting using executor framework and Future. Let's say that I have 100 futures. As of now, I am using Future.get and using the output for subsequent processing. However for further tuning, I want to change the flow as below:

  1. iterate through the set of future tasks and start consuming the result as soon as a future task is complete. I am reading the API doc to understand what might be a good way to accomplish this but reaching out to see if there is a better way to accomplish what I am looking for.

Here is the sample code:

public class ImplCallable implements Callable<String> {
        
        int timeOut;
        ImplCallable(int timeOut) {
            this.timeOut=timeOut;
        }
        
        public String call() throws Exception {
            Thread.sleep(timeOut);
            return Thread.currentThread().getName();
        }
    
    }

and the main class:

public class MainProg {
        public static void main(String...args) throws Exception {
            long startTimeInMillis = System.currentTimeMillis();
            ImplCallable callable1 = new ImplCallable(1000);
            ImplCallable callable2 = new ImplCallable(2000);
            
            
            ExecutorService service = Executors.newFixedThreadPool(4);
            Future<String> task1 = service.submit(callable1);
            Future<String> task2 = service.submit(callable2);
            
            List<Future<String>> futureList = new ArrayList();
            futureList.add(task1);
            futureList.add(task2);
            
            
            String retVal;
            for(Future<String> task:futureList) {
                retVal = task.get();
                //do something with the retVal
            }
            long endTimeInMillis = System.currentTimeMillis();
            
            System.out.println("time taken by code - " + (endTimeInMillis-startTimeInMillis) + "-ms");
        }
    } 

Basically I don't want to use Future.get() and wait for its completion. I want to know if either of the task is complete and use the result as soon as its done.

There are many ways do this so, without a concrete example, you won't get a concrete answer. Likely want to look at CompletableFuture which has many methods for defining follow-on work, combining work, splitting work etc.

Future<String> f = CompletableFuture.supplyAsync(() -> "INITIAL WORK")
  .thenApply(String::toLowerCase) // Do some more work
  .thenAccept(queue::add); // put results onto a queue something is reading from

f.join();
// Batch complete

I hope you are using Java 8 or later version. Whenever you mention "as soon as a future task is complete", you want to use CompletableFuture and its .thenApply() method, as @drekbour suggests.

Then you have multiple threads running different tasks in non-determenistic sequence. But at the end you want to get all the results in the single (Main) thread. To achieve it, you can use CompletableFuture.allOf method, .join() it - and then iterate over all the (already completed) future results without waiting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM