java multithreaded CyclicBarrier use case let the thread start to go

  • 2021-08-21 20:21:32
  • OfStack

1. CyclicBarrier:

A synchronization assistant class, which is used to coordinate multiple sub-threads, so that multiple sub-threads wait in front of this barrier until all sub-threads reach this barrier, and then continue to perform the following actions.

2. Examples of usage scenarios:

At the end of the year, the company organized a league building, requiring every employee to "drive" to the company gate at 8:00 a.m. on Saturday, and then "drive" to the destination.

In this case, the company is the main thread and the employee is the child thread.

3. Code example:


package com.test.spring.support;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/** 
 * @author javaloveiphone
 * @date  Creation time: 2017 Year 1 Month 25 Day   Morning 10:59:11 
 * @Description: 
 */
public class Company {
 public static void main(String[] args) throws InterruptedException {
 // Number of employees 
 int count = 5;
 // Create a counter 
 CyclicBarrier barrier = new CyclicBarrier(count+1);
 // To create a thread pool, you can create it in the following ways 
 //ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1,1,60,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(count));
 ExecutorService threadPool = Executors.newFixedThreadPool(count);
 System.out.println(" The company sends a notice, and every 1 Three employees are in the week 6 Morning 8 Click "self-driving" to meet at the company gate ");
 for(int i =0;i<count ;i++){
  // Adding child threads to the thread pool for execution 
  threadPool.execute(new Employee(barrier,i+1));
  Thread.sleep(10);
 }
 try {
  // Blocks the current thread until all employees arrive at the company gate 
  barrier.await();
  Thread.sleep(10);
  //  Causes the current thread before the latch countdown to zero 1 Wait straight, unless the thread is interrupted or the specified wait time is exceeded. 
  //latch.await(long timeout, TimeUnit unit)
  System.out.println(" All employees have arrived at the company gate, and the company leader 1 And "drive by car" with employees to the event destination. ");
 } catch (InterruptedException e) {
  e.printStackTrace();
 } catch (BrokenBarrierException e) {
  e.printStackTrace();
 }finally{
  // Finally, close the thread pool, but execute previously submitted tasks and do not accept new tasks 
  threadPool.shutdown();
  // Close the thread pool, stop all active tasks in execution, pause processing of waiting tasks, and return to the list of tasks waiting to be executed. 
  //threadPool.shutdownNow();
 }
 }
}
// Distributed worker thread 
class Employee implements Runnable{
 private CyclicBarrier barrier;
 private int employeeIndex;
 public Employee(CyclicBarrier barrier,int employeeIndex){
 this.barrier = barrier;
 this.employeeIndex = employeeIndex;
 }
 @Override
 public void run() {
 try {
  System.out.println(" Employee: "+employeeIndex+" , is going to gather at the company gate ...");
  Thread.sleep(10*employeeIndex);
  System.out.println(" Employee: "+employeeIndex+" , has arrived. ");
  barrier.await();
  Thread.sleep(10);
  System.out.println(" Employee: "+employeeIndex+" "Self-driving" to the destination ");
 } catch (InterruptedException e) {
  e.printStackTrace();
 } catch (BrokenBarrierException e) {
  e.printStackTrace();
 }
 }
}

Print out the possible results:


 The company sends a notice, and every 1 Three employees are in the week 6 Morning 8 Click "self-driving" to meet at the company gate 
 Employee: 1 , is going to gather at the company gate ...
 Employee: 1 , has arrived. 
 Employee: 2 , is going to gather at the company gate ...
 Employee: 3 , is going to gather at the company gate ...
 Employee: 2 , has arrived. 
 Employee: 4 , is going to gather at the company gate ...
 Employee: 5 , is going to gather at the company gate ...
 Employee: 3 , has arrived. 
 Employee: 4 , has arrived. 
 Employee: 5 , has arrived. 
 Employee: 3 "Self-driving" to the destination 
 Employee: 5 "Self-driving" to the destination 
 All employees have arrived at the company gate, and the company leader 1 And "drive by car" with employees to the event destination. 
 Employee: 4 "Self-driving" to the destination 
 Employee: 1 "Self-driving" to the destination 
 Employee: 2 "Self-driving" to the destination 

Note:

The child thread executes the await () method, and must wait for all other child threads to execute the await () method before continuing the subsequent work (await after main). Just like the above example, all self-driving cars must arrive at the company gate before continuing their own self-driving cars to their destinations.

However, the work after await () of the main thread and the work after await () of the child thread are not affected. As long as all the child threads execute the await () method, the main thread can follow up the work at this time, and there is no need to manage the follow-up work of the await () method of the child thread.

4. The difference between CyclicBarrier and CountDownLatch:

1) The parameters passed in for constructing the two objects are different: the parameters for constructing CyclicBarrier are 1 larger than those for constructing CountDownLatch, because the number of constructing CyclicBarrier indicates the number of calls to await (), and the number of constructing CountDownLatch indicates the number of calls to countDown ();

2) After a child thread calls barrier. await (), it must wait for all child threads to complete the call of barrier. await () before continuing its own work, while after a child thread calls latch. countDown (), it will continue its own work without waiting for other child threads to call latch. countDown ().

3), CyclicBarrier can be recycled, while CountDownLatch is not recycled.

4) The program comparison can be seen: java multithreaded CountDownLatch and thread pool ThreadPoolExecutor/ExecutorService use cases

Added: Use of CyclicBarrier, Multithreaded 'Simultaneous' Startup

I won't talk too much, let's just look at the code ~


package com.noway.test.concurrent.cyclicBarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
 *  How to in multithreading ' Simultaneously ' Start multiple threads 
 * @author Noway
 *
 */
public class TestCyclicBarrier {
 public static void main(String[] args) {
 CyclicBarrier cb = new CyclicBarrier(3);
 new Thread(new cbThread(cb," Zhang 3")).start();
 new Thread(new cbThread(cb," Li 4")).start();
 new Thread(new cbThread(cb," Wang 5")).start();
 new Thread(new cbThread(cb," Horse 6")).start();
 new Thread(new cbThread(cb," Small 7")).start();
 }
}
class cbThread implements Runnable{
 private CyclicBarrier cb;
 private String name;
 public cbThread(CyclicBarrier cb, String name) {
 super();
 this.cb = cb;
 this.name = name;
 }
 @Override
 public void run() {
 System.out.println(this.name+" Ready ...");
 try {
  this.cb.await();// Form 1 A barrier 
 } catch (InterruptedException e) {
  e.printStackTrace();
 } catch (BrokenBarrierException e) {
  e.printStackTrace();
 }
 System.out.println(this.name+" Here we go ...");
 }
}

Related articles: