Cannot execute job asynchronously

61 views Asked by At

I have a very confusing issue. I'm combining several Uni<Integer> which takes 4, 6, and 8 seconds respectively. I was expecting them to be executed asynchronously, which means it should only take 8 seconds (the longest) in total. However, when I run the code its taking 18 (4 + 6 + 8) seconds to finish.

Where did I go wrong?

My code:

public Uni<Integer> asyncTask(int idx, int delay) {
    return Uni.createFrom().item(Unchecked.supplier(() -> {
        // Perform your asynchronous operation here
        // Simulate a delay
        try {
            Thread.sleep(delay);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(new Date() + " " + delay);
        return idx; // Example result
    }));
}

public void executeAsyncTasks() {
    Date startTime = new Date();
    Uni.combine().all()
            .unis(asyncTask(1, 4000), asyncTask(2, 6000), asyncTask(3, 8000))
            .asTuple()

            // Subscribe (which will trigger the calls)
            .subscribe().with(tuple -> {
                System.out.println("item 1: " + tuple.getItem1());
                System.out.println("item 2: " + tuple.getItem2());
                System.out.println("item 3: " + tuple.getItem3());
                Date finishTime = new Date();
                System.out.println(finishTime.getTime() - startTime.getTime());
            });
}
2

There are 2 answers

0
Ladicek On BEST ANSWER

You don't want these tasks to be executed asynchronously. You want them to be executed concurrently. In Quarkus, there are 2 ways how to run multiple tasks concurrently:

  • use non-blocking programming, where multiple tasks execute concurrently on a single thread, because they interleave
  • use threads, where each task runs on its own thread

You clearly don't use non-blocking programming, because you're blocking (Thread.sleep()).

You also don't use multiple threads. You may expect Mutiny to create one thread for each task, but that's not how reactive programming libraries work. You'd have to ask for that explicitly.

0
Pendula On

Although Quarkus supports async programming it is based on event loop threading model where there are few I/O threads that carry the tasks/events. Because of this one of most important things is not to block I/O threads. This is exactly what you did in your code with Thread.sleep()

You can find more details and explanations here:

https://quarkus.io/guides/quarkus-reactive-architecture

https://quarkus.io/guides/mutiny-primer