michealAtmi
michealAtmi

Reputation: 1042

Java 8 CompletableFuture future is waiting needlessly for other futures

I have this simple code below. All futures should start at the same time. future13 is supposed to run right after futures 1 and 3 finish, but in the logs I see that it waits until after futures 1, 2, 3, and 4 all finish. Why does it wait for futures 2 and 4?

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import org.junit.Test;


public class Test1 {

    private void loop(Long id, int max) {
        try {
            for (int i = 0; i < max; i++) {
                System.out.println(id);
                Thread.sleep(100);
            }
        } catch (Throwable t) {
            System.out.println(t);
        }
    }

    private CompletableFuture<Void> createConfigFuture(Long id) {
        return CompletableFuture.supplyAsync(() -> {
            loop(id, 100);
            return null;
        });
    }

    @Test
    public void testMe() {
        CompletableFuture<Void> future1 = createConfigFuture(1L);
        CompletableFuture<Void> future2 = createConfigFuture(2L);
        CompletableFuture<Void> future3 = createConfigFuture(3L);
        CompletableFuture<Void> future4 = createConfigFuture(4L);

        try {
            CompletableFuture<Void> future13 = CompletableFuture.allOf(future1, future3)
                .thenApply(v -> {
                    loop(999L, 5);
                    return null;
                });
            CompletableFuture<Void> mainFuture = CompletableFuture.allOf(future13, future2, future4);
            mainFuture.get();

        } catch (InterruptedException | ExecutionException e) {
            System.out.println(e);
        }
    }
}

Upvotes: 3

Views: 1618

Answers (1)

bobah
bobah

Reputation: 18864

There is a queue to get an execution slot in the JRE's default fork-join Executor which all async tasks will serialize on.

The task #2 is ahead of the task #3 in that Executor queue, so before you observe the execution of the task #3 (and, respectively, of the completion task #13) the #2 should get its execution slot first.

This may be seen as #3 linked to #2, but other than that there should not be any additional coupling between the tasks.

Upvotes: 1

Related Questions