Let's take a simple example: we have 2 threads that are doing some mathematical operations and we need to wait for both of them before we proceed with further processing. We could do that using thread's join() method:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class JoiningThreadsExample { | |
public static void main(String[] args) throws InterruptedException { | |
Runnable runnable = new Runnable() { | |
@Override | |
public void run() { | |
for (int i = 0; i < 10000000; i++) { | |
Math.pow(Math.random(), 2); | |
} | |
System.out.println(Thread.currentThread().getName() + " finished"); | |
} | |
}; | |
Thread thread1 = new Thread(runnable); | |
Thread thread2 = new Thread(runnable); | |
thread1.start(); | |
thread2.start(); | |
thread1.join(); | |
thread2.join(); | |
System.out.println("Both threads finished computing."); | |
} | |
} |
That's why the better solution is to use CountDownLatch, "that allows one or more threads to wait until a set of operations being performed in other threads completes", as Javadoc says.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CountdownLatchExample { | |
public static void main(String[] args) throws InterruptedException { | |
int threadsNumber = 2; | |
final CountDownLatch latch = new CountDownLatch(threadsNumber); | |
Runnable runnable = new Runnable() { | |
@Override | |
public void run() { | |
for (int i = 0; i < 10000000; i++) { | |
Math.pow(Math.random(), 2); | |
} | |
System.out.println(Thread.currentThread().getName() + " finished"); | |
latch.countDown(); | |
} | |
}; | |
ExecutorService executorService = Executors.newFixedThreadPool(threadsNumber); | |
executorService.submit(runnable); | |
executorService.submit(runnable); | |
latch.await(); | |
executorService.shutdown(); | |
System.out.println("Both threads finished computing."); | |
} | |
} |
If threads must repeatedly count down in a similar way, we would need to use CyclicBarrier instead.
No comments:
Post a Comment