Execute a for loop in parallel using CompletableFuture in Java and log the execution

僤鯓⒐⒋嵵緔 提交于 2019-12-05 18:34:15

You have to collect all CompletableFutures and wait for their complete:

log("Started doing things");
List<CompletableFuture> futures = new ArrayList();
for (int i = 0; i < 10000; i++) {
    futures.add(CompletableFuture.runAsync(() -> doSomething()));
    futures.add(CompletableFuture.runAsync(() -> doSomethingElse()));
}
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                 .thenRunAsync(() -> log("Ended doing things"));

Or when you use the ExecutorService:

CompletableFuture.runAsync(() -> {
    try {
        executorService.invokeAll(tasks);
    } catch (InterruptedException) {
        e.printStackTrace();
    }
    log("Ended doing things");
});

I suppose CompletableFuture is the wrong concept for your needs. If you want to execute an arbitrary number of similar tasks in parallel, the easiest thing is to use the method invokeAll(...) on an ExecutionService:

// First, create a list with all tasks you want to execute in parallel
List<Callable<?>> tasks = new ArrayList<>(10000);
for (int i = 0; i < 10000; ++i) {
    // we need to create Callables, so if your doSomething method returns void, we have to convert it to a Callable using helper method from class Executors
    tasks.add(Executors.callable(this::doSomething));
}

// Then, create an executor service that can execute these tasks
// There are different executors you can choose from, I take one that has a fixed pool of threads
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

// Last but not least, call invokeAll to execute all tasks and wait for them to complete
executorService.invokeAll(tasks);

// This method will be called when all tasks have been completed successfully:
System.out.println("done");

The trick here is to use the CompletableFuture.allOf. Try this out.

public static void main(String[] args) {
    System.out.println("Started doing things");
    List<CompletableFuture<Void>> cfList = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        CompletableFuture<Void> cfOne = CompletableFuture.runAsync(() -> doSomething());
        CompletableFuture<Void> cfTwo = CompletableFuture.runAsync(() -> doSomethingElse());
        cfList.addAll(Arrays.asList(cfOne, cfTwo));
    }
    CompletableFuture<Void> allCfs = CompletableFuture.allOf(cfList.toArray(new CompletableFuture<?>[0]));
    allCfs.thenRunAsync(() -> System.out.println("Ended doing things"));
}

This implementation will NOT keep your main thread waiting till you complete all the submitted tasks.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!