In the development process, there will be more or less one method that needs to wait for the execution results of two or more threads. How do we deal with this? Here java provides two methods, CountDownLatch and CyclicBarrier. Here are some examples:
CountDownLatch is a method under the java.util.concurrent package, as shown in the following example:
private static void testCountDownLatch() { //Create a CountDownLatch,Count passed in 2, i.e. wait for two threads to finish counting to 0 before execution can continue //Note here that the creation must be final Otherwise, it cannot be called countDown()Method final CountDownLatch cdl = new CountDownLatch(2); //Thread 1 starts execution new Thread(new Runnable() { public void run() { System.out.println("Thread 1 starts execution"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("End of thread 1"); //Count minus 1 at the end of execution cdl.countDown(); } }).start(); //Thread 1 starts execution new Thread(new Runnable() { public void run() { System.out.println("Thread 2 starts execution"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("End of thread 1"); //Count minus 1 at the end of execution cdl.countDown(); } }).start(); try { //Thread waiting, when the count is 0, execution can continue cdl.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Go ahead"); }
Execution result:
Thread 1 starts execution Thread 2 starts execution End of thread 1 End of thread 2 Go aheadBe careful:
Countdownlatch is not possible to reinitialize (final) or modify the value of the counter inside the countdownlatch object (i.e. it is not possible to re count or add a count)
CyclicBarrierCyclicBarrier is also a method under the java.util.concurrent package, as shown in the following example:
private static void testCyclicBarrier() { //Create a CyclicBarrier,Count passed in 3, i.e. wait for two threads to finish counting 1 before execution can continue final CyclicBarrier cb = new CyclicBarrier(3); //Thread 1 starts execution new Thread(new Runnable() { public void run() { System.out.println("Thread 1 starts execution"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("End of thread 1"); //Encounter barriers try { cb.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }).start(); //Thread 1 starts execution new Thread(new Runnable() { public void run() { System.out.println("Thread 2 starts execution"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("End of thread 2"); //Encounter barriers try { cb.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }).start(); try { //Block, continue when count is 1 cb.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println("Go ahead"); }
Results: same as above
Note: the delivery count of CyclicBarrier is one more than that of thread (I don't know why here. You can see the source code if you are interested. It should be about 3 times of await (), each time the count is reduced by 1, and it can continue to execute when the count is 0). reset() method is provided to handle more complex logic