javamultithreadingasynchronouscompletable-futurework-stealing

Use CompletableFuture on ForkJoinpool and avoid thread waiting


Hello I thought with CompletableFuture and the default ForkJoinPool I could optimize execution of task more than a classic ExecutorService but I missing something

With this code the execution takes 1 seconds, I have 3 worker threads:

for (int i = 0; i < 3; i++) {
    final int counter = i;
    listTasks.add(CompletableFuture.supplyAsync(() -> {
        Thread.sleep(1000);
        System.out.println("Looking up " + counter + " on thread " + Thread.currentThread().getName());
        return null;
    }));
}

OK, seems normal.

But with this code, it takes 3 seconds:

for (int i = 0; i < 9; i++) {
    final int counter = i;
    listTasks.add(CompletableFuture.supplyAsync(() -> {
        Thread.sleep(1000);
        System.out.println("Looking up " + counter + " on thread " + Thread.currentThread().getName());
        return null;
    }));
}

I thought that sleeping thread would be used to launch other waiting task, it should takes also 1 seconds. I've read for example that IO WAINTING thread state would mean that thread can be reused for other task. Can I test this behaviour with Thread.sleep()? Does my test method is wrong or did I understand something wrongly?


Solution

  • A sleeping thread cannot be used to do the job of another thread (especially, one thread cannot sleep for another thread). It's only CPU that can switch to the second thread when the first one goes to sleep.

    When you provide a task to CompletableFuture.supplyAsync(), it goes to the default instance of ForkJoinPool that has as many threads as your computer has CPUs. You manually set allocated three threads to your default ForkJoinPool, so your nine tasks are distributed equally between them: each thread executes three tasks consecutively. So, you have three seconds as the result.