Question: What is a way to simply wait for all threaded process to finish? For example, let's say I have:

```
public class DoSomethingInAThread implements Runnable{

    public static void main(String[] args) {
        for (int n=0; n<1000; n++) {
            Thread t = new Thread(new DoSomethingInAThread());
            t.start();
        }
        // wait for all threads' run() methods to complete before continuing
    }

    public void run() {
        // do something here
    }

}

```

How do I alter this so the `main()` method pauses at the comment until all threads' `run()` methods exit? Thanks!

Answer: 
One way would be to make a `List` of `Thread`s, create and launch each thread, while adding it to the list. Once everything is launched, loop back through the list and call `join()` on each one. It doesn't matter what order the threads finish executing in, all you need to know is that by the time that second loop finishes executing, every thread will have completed.

A better approach is to use an [ExecutorService](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html) and its associated methods:

```
List<Callable> callables = ... // assemble list of Callables here
                               // Like Runnable but can return a value
ExecutorService execSvc = Executors.newCachedThreadPool();
List<Future<?>> results = execSvc.invokeAll(callables);
// Note: You may not care about the return values, in which case don't
//       bother saving them

```

Using an ExecutorService (and all of the new stuff from Java 5's [concurrency utilities](http://java.sun.com/j2se/1.5.0/docs/guide/concurrency/)) is incredibly flexible, and the above example barely even scratches the surface.
The problem with:

```java
for(i = 0; i < threads.length; i++)
  threads[i].join();

```

...is, that `threads[i + 1]` never can join before `threads[i]`.
Except the "latch"ed ones, all solutions have this lack.

No one here (yet) mentioned [ExecutorCompletionService](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/ExecutorCompletionService.html), it allows to join threads/tasks according to their completion order:

> 
> `public class ExecutorCompletionService<V>`
> `extends Object`
> `implements CompletionService<V>`
> 
> 
> A `CompletionService` that uses a supplied `Executor` to execute tasks. This class arranges that submitted tasks are, upon completion, placed on a queue accessible using take. The class is lightweight enough to be suitable for transient use when processing groups of tasks.
> 
> 
> **Usage Examples.**
> 
> 
> Suppose you have a set of solvers for a certain problem, each returning a value of some type Result, and would like to run them concurrently, processing the results of each of them that return a non-null value, in some method `use(Result r)`. You could write this as:
> 
> 
> 
> ```java
> void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException, ExecutionException {
>   CompletionService<Result> cs = new ExecutorCompletionService<>(e);
>   solvers.forEach(cs::submit);
>   for (int i = solvers.size(); i > 0; i--) {
>     Result r = cs.take().get();
>     if (r != null)
>       use(r);
>   }
> }
> 
> ```
> 
> Suppose instead that you would like to use the first non-null result of the set of tasks, ignoring any that encounter exceptions, and cancelling all other tasks when the first one is ready:
> 
> 
> 
> ```java
> void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException {
>   CompletionService<Result> cs = new ExecutorCompletionService<>(e);
>   int n = solvers.size();
>   List<Future<Result>> futures = new ArrayList<>(n);
>   Result result = null;
>   try {
>     solvers.forEach(solver -> futures.add(cs.submit(solver)));
>     for (int i = n; i > 0; i--) {
>       try {
>         Result r = cs.take().get();
>         if (r != null) {
>           result = r;
>           break;
>         }
>       } catch (ExecutionException ignore) {}
>     }
>   } finally {
>     futures.forEach(future -> future.cancel(true));
>   }
> 
>   if (result != null)
>     use(result);
> }
> 
> ```
> 
> #### Since: 1.5 (!)
> 
> 
> 

Assuming `use(r)` (of Example 1) also asynchronous, we had a big advantage. #