Java does not use all available CPUs Java does not use all available CPUs multithreading multithreading

Java does not use all available CPUs


You are submitting jobs and calling join() right afterwards, waiting for the completion of the asynchronous job.

Stream intermediate steps are executed element-wise, which means that the intermediate step .map(CompletableFuture::join) runs on one element at a time (even worse as it's a sequential stream), without making sure all elements have gone through the submission step. This causes the thread to block while waiting for the completion of each single calculation.

You have to enforce a submission of all jobs before starting to call join() on them:

List<MyResult> results =    myInputList.stream()               .map(myService::getResultFuture)               .collect(Collectors.toList()).stream()               .map(CompletableFuture::join)               .collect(Collectors.toList());

If you can express whatever you want to do with the results list as an action to be invoked when everything is done, you can implement the operation in a way that does not block threads with join():

List<CompletableFuture<MyResult>> futures = myInputList.stream()    .map(myService::getResultFuture)    .collect(Collectors.toList());CompletableFuture.allOf(futures.toArray(CompletableFuture<?>[]::new))    .thenRun(() -> {        List<MyResult> results = futures.stream()            .map(CompletableFuture::join)            .collect(Collectors.toList());        // perform action with results    });

It still calls join() to retrieve the result, but at this point, all futures have been completed so the caller won’t get blocked.