Reputation: 159
I have a loop which create a new Thread on each iteration, like so:
for(int i = 0; i < REPEAT; i++) {
new Thread(new MyTask(i)).start();
Thread.sleep(1);
}
private void finalTask() {
//Some code to be executed once every threads stopped running
}
Where MyTask is a class implementing Runnable. My goal is: I would like to run finalTask once every threads stopped. To achieve this, I have tried incrementing a variable by 1 each time a thread finished running, and once this variable was equal to REPEAT, the final task would run. But this didn't work. I've searched on Google and StackOverlow for answers to my problem, but there are very little informations on this and none of them worked as well. There would always be a thread that was running after the final task. How can I do this then?
Upvotes: 3
Views: 1283
Reputation: 14999
You can put them into CompletableFuture
s and then use whenComplete()
.
CompletableFuture[] all =
IntStream.range(0, REPEAT+1).
.mapToObj(i -> CompletableFuture.supplyAsync(new MyTask(i)))
.toArray(CompletableFuture[]::new) ;
CompletableFuture.allOf(all).whenComplete((r, t) -> {
// your code here
}) ;
Upvotes: 0
Reputation: 1
Another simple way is to just join()
on all the threads and then call finalTask()
:
Thread tasks[] = new Thread[REPEAT];
for(int i = 0; i < REPEAT; i++) {
tasks[i] = new Thread(new MyTask(i));
tasks[i].start();
}
for (Thread task : tasks) {
for (;;) {
try {
task.join();
break;
}
catch ( InterruptedException e ) {
// catch code here
}
}
}
finalTask();
Note there's almost more code used to handle the possible InterruptedException
from the join()
method call than used to implement the rest of the processing.
Upvotes: 1
Reputation: 17890
You can use a CountDownLatch
for this. A CountDownLatch is
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
CountDownLatch countDownLatch = new CountDownLatch(REPEAT);
for (int i = 0; i < REPEAT; i++) {
new Thread(new MyTask(i, countDownLatch)).start();
Thread.sleep(1);
}
finalTask(countDownLatch);
I create a CountDownLatch whose count
is initialized to the value of REPEAT
. I pass this to each of the threads and to the finalTask
method.
Each thread after doing its work should call the countDown
method of the countDownLatch.
private static class MyTask implements Runnable {
private int i;
private CountDownLatch countDownLatch;
private MyTask(int i, CountDownLatch countDownLatch) {
this.i = i;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
//Perform some task
System.out.println("Running " + i);
countDownLatch.countDown();
}
}
The first line of the finalTask
method should call the await
method of the CountDownLatch. This will cause the thread running the finalTask
wait till the count of the CountDownLatch reaches 0 i.e., until all threads (REPEAT number of them) has completed and invoked the countDown
of the CountDownLatch.
private static void finalTask(CountDownLatch countDownLatch) {
try {
countDownLatch.await(); //this will wait until the count becomes 0.
} catch (InterruptedException e) {
e.printStackTrace(); //handle it appropriately
}
//Some code to be executed once all threads stopped running
System.out.println("All done");
}
Upvotes: 2