简体   繁体   中英

Java Waiting for all threads to complete

Edit: My question is different, it has no relevance to the linked question.

I've following code with completion handler.

FutureTask<Void> futureTask = new FutureTask<Void>(() -> {
    System.out.println("callback");
    return null;
});

Runnable task = () -> {
    for(int i=0; i<5; i++) {
        System.out.println(Thread.currentThread().getName() + " " + i);
    }
    futureTask.run();
};

new Thread(task).start();
new Thread(task).start();

Basically I'm looking for completion handler for variable number of tasks, or is there another approach?

I'm inspired from this answer but seems it's part of some library while I'm looking for a native solution.

Completable Future ???

Here's my attempt with completable futures with the result handler at the end.

public void test() {
    CompletableFuture
            .supplyAsync(() -> method1())
            .supplyAsync(() -> method2())
            .supplyAsync(() -> result());
}

public String method1() {
    System.out.println("calling 1");
    return "method1";
}

public String method2() {
    System.out.println("calling 2");
    return "method2";
}

public String result() {
    System.out.println("result");
    return "result";
}

Assuming that your method result() returns a value that you want to retrieve, ie is declared like Type result() , you can use

CompletableFuture<Type> f = CompletableFuture.allOf(
    CompletableFuture.runAsync(() -> method1()),
    CompletableFuture.runAsync(() -> method2())
).thenApply(_void -> result());

Each runAsync creates an individual asynchronous CompletableFuture that will be completed once the Runnable has been executed. It's the same as supplyAsync , except that it doesn't return a result.

allOf create a CompletableFuture that will be completed, once all specified futures are completed, hence, any chained dependent action will only run after all futures have been completed. By using thenApply we create a dependent future that will be completed with the return value of result() .

If result() is not intended to return a value, but just an action that should run after all other actions have been completed, you can use

CompletableFuture.allOf(
    CompletableFuture.runAsync(() -> method1()),
    CompletableFuture.runAsync(() -> method2())
).thenRun(() -> result());

instead.

One easy approach is to submit your Runnable(s) to an ExecutorService, then call shutdown , then call awaitTermination :

ExecutorService executor = Executors.newWorkStealingPool();
executor.submit(task);
executor.submit(task);

executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);

No need to use CompletableFuture.

Save the links to the threads you've created, and call join()

Thread a = new Thread(task);
Thread b = new Thread(task);
a.start();
b.start();

a.join();
b.join();
//guaranteed that both threads have completed here

Depending on how much control you want you could use a ThreadPoolExecutor:

tpe.execute(Runnable);

Wait for the active count == 0;

then shutdown the executor.

Or keep the threads in a structure.

Wait for an specific TTL then interrupt them if the state is RUNNABLE

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM