2

I want to run a few tasks simultaneously so I have a code that looks like this:

for(final Task task : tasks){
    (new Thread(){public void run(){
        task.run(args);
}}).start();

How can I know when all of the tasks are done (the amount of tasks can vary) so that I can run something only after everything is done?

System.out.println("All tasks are finished");
Artemio Ramirez
  • 1,116
  • 1
  • 10
  • 23
  • There is a `Thread.getState()` method that can tell you when a thread is terminated, but I don't think you can do that with anonymous `Thread`s. – NAMS Apr 21 '16 at 16:49

6 Answers6

5

Instead of creating Threads explicitly, submit your Runnables to an ExecutorService, then call its shutdown and awaitTermination methods:

ExecutorService executor = Executors.newFixedThreadPool(tasks.size());

for (final Task task : tasks) {
    executor.submit(new Runnable() {
        @Override
        public void run() {
            task.run(args);
        }
    });
}

executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLSECONDS);
VGR
  • 40,506
  • 4
  • 48
  • 63
  • Does "ExecutorService.awaitTermination()" works like "Process.waitFor()"? Meaning the following code will wait and execute on it's own after waiting is over? Or do I still have to be checking myself if the execution is over? (Like in the other answers) – Artemio Ramirez Apr 21 '16 at 17:21
  • @ArtemioRamirez I believe the documentation (to which I’ve linked) answers that. – VGR Apr 21 '16 at 17:28
  • I didn't realize those were actual links, my bad. I thought it was just good formatting. Ty – Artemio Ramirez Apr 21 '16 at 17:35
  • 1
    This is the best option in Java 7, but in Java 8 I would use parallelStream(0 (see my answer) – Peter Lawrey Apr 21 '16 at 18:19
  • 4
    Alternately, instead of terminating the thread pool (if you want to use an existing thread pool), you can use `ExecutorService.invokeAll()` and wait on the resulting `Future`s. – Brian Goetz Apr 21 '16 at 18:26
5

A shorter version is to use a parallelStream

tasks.parallelStream().forEach(t -> t.run(args));

This will run all the tasks, using all the CPUs you have (if you have enough tasks) and wait for the all to finish.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
1

You can also use a CountDownLatch to indicate if the threads are complete. See https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html

Like so:

public static class Task {
    void run(String args[]) {
        System.out.println("Hello");
    }
}

public static void main(String[] args) {
    List<Task> tasks = Arrays.asList(new Task(), new Task(), new Task());
    CountDownLatch doneSignal = new CountDownLatch(tasks.size());

    for(final Task task : tasks) {
        (new Thread() {
            public void run(){
                task.run(args);
            }
        }).start();
        doneSignal.countDown();  //counts latch down by one
    }

    //A
    new Thread() {
        public void run() {
            try {
                doneSignal.await(); //blocks until latch counted down to zero
                System.out.println("All tasks completed");
            } catch(Exception e) {
                System.out.println("Warning: Thread interrupted.");
            }
        }
    }.start();
}

Each task thread will count the latch down by one when they complete. The Thread created at //A will wait until the latch has been count down to zero. Only then, the "All tasks completed" statement will be printed. So basically the statement after doneSignal.await() will only execute after all threads have completed.

mdewit
  • 2,016
  • 13
  • 31
1

Use CyclicBarrier , example : http://tutorials.jenkov.com/java-util-concurrent/cyclicbarrier.html

Dave
  • 35
  • 10
0

Simply add each thread to a list when you create it:

LinkedList<Thread> threads = new LinkedList<>();

And when you make a new thread:

Thread t = new Thread() {
    public void run() {
        task.run(args);
    }
}
threads.add(t);

Then you can check each thread in your list to see if it is finished:

boolean allFinished = true;

for (Thread t : threads) {
 if (t.isAlive()) {
  allFinished = false;
  break;
 }
}

See this link for more info on checking if threads are finished:

How to know if other threads have finished?

The key point in this questions is that if you want to check on threads later, you MUST store a list (or array, etc) of them somewhere.

Community
  • 1
  • 1
nhouser9
  • 6,730
  • 3
  • 21
  • 42
0

Another way is to use the Future interface. Doing it this way gives you some other nifty features. See this for some examples.

snerd
  • 1,238
  • 1
  • 14
  • 28