Matthias Ronge
Matthias Ronge

Reputation: 10122

Is there a short-hand to call several functions in parallel in Java?

Given I have a function in Java which has to do a lot of work. This work consists of several different things to do, which are defined in their own functions and are independent of each other.

void myFunction() {
    foo();
    bar();
}

However, these functions run one after the other (just as I coded it), which is not necessary here and makes the whole function run longer than necessary. Running both functions in its own thread requires significantly more code:

void myFunction() {
    UncaughtExceptionHandler eh = (th, t) -> { throw new UndeclaredThrowableException(t); };
    try {
        Thread foo = new Thread(() -> foo());
        Thread bar = new Thread(() -> bar());
        foo.setUncaughtExceptionHandler(eh);
        bar.setUncaughtExceptionHandler(eh);
        foo.start();
        bar.start();
        foo.join();
        bar.join();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}

So I wonder if there is some built-in approach in newer Java versions to do this more efficiently, something like:

Threads.doParallel(
    () -> foo(),
    () -> bar()
);

Upvotes: 4

Views: 142

Answers (3)

bowmore
bowmore

Reputation: 11310

The shortest I get, using CompletableFutures is this :

CompletableFuture.allOf(
        CompletableFuture.runAsync(new FutureTask<Void>(() -> foo(), null)),
        CompletableFuture.runAsync(new FutureTask<Void>(() -> bar(), null))
).get();

This doesn't have the handling for excptions in foo() or bar(). But we can add that, sacrificing some brevity :

CompletableFuture.allOf(
        CompletableFuture.runAsync(new FutureTask<Void>(() -> foo(), null)),
        CompletableFuture.runAsync(new FutureTask<Void>(() -> bar(), null))
)
.exceptionally(t -> {
    throw new UndeclaredThrowableException(t);
})
.get();

Upvotes: 3

saurabh.in
saurabh.in

Reputation: 409

Here is an example using CompletionService which could run tasks concurrently and collect the results as they become ready.

    public void doParallel() {
        Executor executor = Executors.newCachedThreadPool();
        CompletionService<Boolean> completionService = new ExecutorCompletionService<>(executor);
        Future future1 = completionService.submit( () -> foo() );
        Future future2 = completionService.submit( () -> bar() );
        try {
            completionService.take();
            completionService.take(); // second task
        } catch ( InterruptedException e ) {
            e.printStackTrace();
        } finally {
            future1.cancel( true );
            future2.cancel( true );
        }
    }

Upvotes: 1

madhead
madhead

Reputation: 33442

Use ExecutorService:

final ExecutorService executor = Executors.newFixedThreadPool(10);
final Runnable foo = () -> ...;
final Runnable bar = () -> ...;

executor.submit(foo);
executor.submit(bar);

executor.shutdown();

Upvotes: 2

Related Questions