How to wait for the completion of several tasks in Java?

What is the correct way to implement concurrency in Java applications? I know about Threads, etc., Of course, I have been programming for Java for 10 years, but did not have much experience with concurrency.

For example, I have to load several resources asynchronously, and only after all of them have been loaded can I continue to work and do more work. Needless to say, there is no order how they finish. How to do it?

In JavaScript, I like to use the jQuery.deferred to say

 $.when(deferred1,deferred2,deferred3...) .done( function(){//here everything is done ... }); 

But what should I do in Java?

+7
java multithreading concurrency
source share
7 answers

If I do not use parallel threads or Spring MVC TaskExecutor, I usually use CountDownLatch . Instant C # tasks, reduce once for each thread that completes its task. CountDownLatch.await() waits until the latch is at 0. Really useful.

Read more here: JavaDocs

+2
source share

You can achieve this in several ways.

1. ExecutorService invokeAll() API

Performs specified tasks, returning a list of futures that maintain their status and results when everything is completed.

2. CountDownLatch

A synchronization helper that allows one or more threads to wait for a set of operations in other threads to complete.

A CountDownLatch initialized by this count. Waiting methods are executed until the current counter reaches zero due to calls to the countDown() method, after which all waiting threads are freed and any subsequent calls wait immediately. This is a one-time occurrence - the score cannot be reset. If you need a version that resets a counter, consider using CyclicBarrier.

3. ForkJoinPool or newWorkStealingPool() in Executors is another way

Take a look at SE related questions:

How to wait for a thread that spawns its own thread?

Performers: how to synchronously wait for the completion of all tasks if tasks are created recursively?

+4
source share

I would use a parallel thread.

 Stream.of(runnable1, runnable2, runnable3).parallel().forEach(r -> r.run()); // do something after all these are done. 

If you need this to be asynchronous, you can use a pool or thread.

I need to load multiple resources asynchronously,

You can collect these resources as follows.

 List<String> urls = .... Map<String, String> map = urls.parallelStream() .collect(Collectors.toMap(u -> u, u -> download(u))); 

This will give you a mapping of all resources once they are loaded at the same time. concurrency will be the number of processors that you default.

+3
source share
+1
source share

This is an example of using Threads. Its a static executerService with a fixed size of 50 threads.

 public class ThreadPoolExecutor { private static final ExecutorService executorService = Executors.newFixedThreadPool(50, new ThreadFactoryBuilder().setNameFormat("thread-%d").build()); private static ThreadPoolExecutor instance = new ThreadPoolExecutor(); public static ThreadPoolExecutor getInstance() { return instance; } public <T> Future<? extends T> queueJob(Callable<? extends T> task) { return executorService.submit(task); } public void shutdown() { executorService.shutdown(); } } 

The business logic for executer is used as follows: (You can use Callable or Runnable. Callable can return something, Runnable not)

 public class MultipleExecutor implements Callable<ReturnType> {//your code} 

And the call to executer:

 ThreadPoolExecutor threadPoolExecutor = ThreadPoolExecutor.getInstance(); List<Future<? extends ReturnType>> results = new LinkedList<>(); for (Type Type : typeList) { Future<? extends ReturnType> future = threadPoolExecutor.queueJob( new MultipleExecutor(needed parameters)); results.add(future); } for (Future<? extends ReturnType> result : results) { try { if (result.get() != null) { result.get(); // here you get the return of one thread } } catch (InterruptedException | ExecutionException e) { logger.error(e, e); } } 
+1
source share

The same behavior as with $.Deferred in jQuery , you can archive in Java 8 with the class CompletableFuture . This class provides an API for working with Promises . To create asynchronous code, you can use one of it static creation methods, such as #runAsync , #supplyAsync . Then applying some calculation of the results with #thenApply .

+1
source share

Usually I choose the async method notify-start, notify-progress, notify-end:

 class Task extends Thread { private ThreadLauncher parent; public Task(ThreadLauncher parent) { super(); this.parent = parent; } public void run() { doStuff(); parent.notifyEnd(this); } public /*abstract*/ void doStuff() { // ... } } class ThreadLauncher { public void stuff() { for (int i=0; i<10; i++) new Task(this).start(); } public void notifyEnd(Task who) { // ... } } 
0
source share

All Articles