From the school to A factory all the way sunshine vicissitudes of life

Please go to www.codercc.com


1. CountDownLatch

In a multithreaded collaborative business function, sometimes need to wait for other threads to complete the task, the main Thread to continue to perform business functions, in this business scenario, usually can use the join method of the Thread class, make the main Thread waiting to be join after a Thread execution, the main Thread to continue to perform. Of course, this can also be done using an inter-thread message communication mechanism. In fact, the Java concurrency utility class provides us with a utility class like “Countdown”, which can be very convenient to accomplish this kind of business scenario.

To understand CountDownLatch, take a very popular example. When runners are running, assume that there are six runners participating in the race, and the referee will time each of them at the end of the race. It can be imagined that when one runner reaches the end of the race, there is no timing task for the referee. The referee’s task is not finished until all the athletes have reached the finish line. The 6 runners can be likened to the 6 threads, which, when calling the countdownlatch. countDown method, decrement the counter value by one until the count reaches zero and the referee (the thread calling the await method) can proceed.

Here are some important ways to CountDownLatch.

Start with the CountDownLatch constructor:

public CountDownLatch(int count)
Copy the code

The constructor passes in an integer N, which is then reduced by one by the countDown method calling CountDownLatch until N falls to 0 and the thread currently calling the await method continues.

There are not many methods for CountDownLatch, so let’s list them one by one:

  1. Await () throws InterruptedException: The thread calling the method waits until the N passed by the constructor is reduced to 0 before continuing;
  2. Await (long timeout, TimeUnit unit) : functions the same as the await method above, except with a time limit. The calling thread waits for a specified timeout and continues execution, regardless of whether N is reduced to 0;
  3. CountDown () : Reduces the initial CountDownLatch value N by 1;
  4. Long getCount() : retrieves the value currently maintained by CountDownLatch;

Here’s an example of how CountDownLatch can be used:

public class CountDownLatchDemo { private static CountDownLatch startSignal = new CountDownLatch(1); Private static CountDownLatch endSignal = new CountDownLatch(6);

public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(6); for (int i = 0; i < 6; Executorservice.execute (() -> {try {system.out.println (thread.currentThread ().getName() + "executorService.execute() -> {try {system.out.println (thread.currentThread ().getName() +" ); startSignal.await(); System.out.println(thread.currentThread ().getName() + "currentThread() "); endSignal.countDown(); System.out.println(thread.currentThread ().getName() + "thread.currentThread () "); } catch (InterruptedException e) { e.printStackTrace(); }}); } system.out. println(" umpire calls the shots!! ") ); startSignal.countDown(); endSignal.await(); System.out.println(" All runners reach the finish line, the race ends!" ); executorService.shutdown(); }} Output:

Copy the code

Pool-1-thread-2 athletes wait for the referee's whistle!! Pool-1-thread-3 athletes wait for the referee's whistle!! Pool-1-thread-1 athletes wait for the referee's whistle!! Pool-1-thread-4 athletes wait for the referee's whistle!! Pool-1-thread-5 athletes wait for the referee's whistle!! Pool-1-thread-6 players wait for the referee's whistle!! The referee calls the shots!! Pool-1 Thread-2 is sprinting to the finish line. Pool-1 Thread-2 is sprinting to the finish line. Pool-1 Thread-2 is sprinting to the finish line Reach the finish line - thread pool - 1-1 - thread pool - 1-4 are struggling to sprint to the finish - thread pool - 1-4 - thread pool - 1-5 are struggling to sprint - thread pool - 1-5 to the finish Pool-1-thread-6 is sprinting to the finish Line All runners have reached the finish line, the race is over!

The sample code sets up two countdownlatches. The first endSignal is used to control that the main thread (referee) must wait until the other thread (athlete) has reduced the number N maintained by CountDownLatch to zero. The other startSignal is used by the main thread to “command” other threads. The CountDownLatch referenced by startSignal starts at 1, All other threads will block with startsignal.await () until the main thread calls startsignal.countdown (); CountDownLatch maintains a value of N equal to 0 before other threads can execute. CountDown () is CountDownLatch (). Subtracting the value maintained by endSignal by one, because six tasks submitted to the thread pool are subtracted six times, the value maintained by endSignal eventually becomes zero, so the main thread latches.await(); The blocking is complete before the execution continues.

Also, note that when the countDown method of CountDownLatch is called, the current thread will not block and will continue to execute, as in this case, the output of Pool-1-Thread-4 will continue to the end.

2. CyclicBarrier

CyclicBarrier is also a multithreaded concurrency control utility that has the same wait count functionality as CountDownLatch, but is more powerful than CountDownLatch.

To understand cyclicbarriers, here is a colloquial example. In a sports meeting, there will be running. Let’s simulate the situation when athletes enter the stadium. Assuming there are six tracks, at the beginning of the game, six athletes need to stand at the starting point at the beginning of the game, and the referee can only start running after blowing his whistle. The starting point of the track is equivalent to the barrier, which is the critical point. If the 6 runners are analogous to threads, that is, all the 6 threads must reach the specified point, which means that a wave is formed, and then the execution can continue. Otherwise, each thread has to block and wait until a wave is formed. Cyclic is a cyclic barrier, which means that a CyclicBarrier remains in force after multiple threads have completed a wave and can continue to complete the next wave. CyclicBarrier is executed as follows:

CyclicBarrier execution schema.jpg

When multiple threads have reached the specified point, the execution can continue. This is a bit like counting off, assuming that six threads are equal to six runners, and when they get to the start of the track they count off, and if it happens to be six, the wave is complete and can proceed. One of the differences with CountDownLatch is that CyclicBarrier remains in effect after being used once and can continue to be used as a counter. ** The six threads here, the initial value of the counter, 6, were passed in through the CyclicBarrier constructor.

Here are the main methods of CyclicBarrier:

// Wait until all threads reach the specified threshold await() throws InterruptedException, BrokenBarrierException

// Same functionality as the await method above, except that there is a timeout limit, Block wait until timeout is reached await(long timeout, TimeUnit Unit) throws InterruptedException, BrokenBarrierException, TimeoutException

Int getNumberWaiting()

Boolean isBroken()

Copy the code

// Reset the barrier to its initial state. A BrokenBarrierException is thrown if a thread is currently waiting on a critical point. void reset()

Note also that CyclicBarrier provides this constructor:

public CyclicBarrier(int parties, Runnable barrierAction)
Copy the code

BarrierAction can be used to pass in the next operation when the specified thread has reached the specified critical point.

A case in point

CyclicBarrier: CyclicBarrier: CyclicBarrier: CyclicBarrier: CyclicBarrier: CyclicBarrier: CyclicBarrier

Public class CyclicBarrierDemo {private static CyclicBarrier barrier = new CyclicBarrier(6, 1) () -> {system.out.println (" all athletes enter the stadium, the referee gives the order !!!!!" ); }); Public static void main(String[] args) {system.out.println (" );
ExecutorService service = Executors.newFixedThreadPool(6); for (int i = 0; i &lt; 6; i++) { service.execute(() -&gt; {try {system.out.println (thread.currentThread ().getName() + "athlete "); barrier.await(); System.out.println(thread.currentThread ().getName() + ""); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); }}); }}Copy the code

}

Copy the code

Output results: athletes ready to enter the arena, the audience cheers............ Pool-1-thread-1 player, pool-1-thread-1 player, pool-1-thread-3 player, pool-1-thread-4 player, pool-1-thread-5 player, Enter pool-1-thread-6 athletes, enter all athletes, at the referee's command !!!!! Pool 1-thread-6 Player Pool 1-thread-1 Player Pool 1-thread-5 Player Pool 1-thread-4 Player Pool 1-thread-3 Player pool 1-thread-3 player Pool 1-thread-6 player Pool 1-thread-1 player Pool 1-thread-3 player Pool 1 Pool-1-thread-2 athletes start

As can be seen from the output, execution can proceed only when all six runners (threads) have reached the specified barrier, otherwise it will block waiting to call await()

3. Comparison of CountDownLatch and CyclicBarrier

CountDownLatch and CyclicBarrier are both utility classes for controlling concurrency and can be understood as maintaining a counter, but they have different priorities:

  1. CountDownLatch is typically used when thread A waits for several other threads to complete their tasks before it executes. A CyclicBarrier is typically used when a group of threads wait for each other to reach a state and then execute simultaneously. CountDownLatch emphasizes the need for one or more threads to accomplish something. Cyclicbarriers are threads that wait for each other to complete and then work together.
  2. After the countDown method of CountDownLatch is called, the current thread does not block and continues to execute; Calling the await method of CyclicBarrier blocks the current thread until all CyclicBarrier threads have reached the specified point.
  3. CountDownLatch has fewer and simpler methods, while CyclicBarrier provides more methods, such as getNumberWaiting() and isBroken(), to get the state of multiple threads. And the CyclicBarrier constructor can pass in the barrierAction, specifying the business function to perform when all threads arrive;
  4. CountDownLatch is not reusable, while CyclicBarrier is.