Today we will learn about the CountDownLatch class, which has a similar function to join. Then we will search for the difference between them. So make a note here.

In the current thread, if the join method of a thread is called, the current thread will be blocked until the thread is finished executing. The principle of join is to continuously check whether the thread is alive. If the thread is alive, let the current thread wait until the thread terminates, and the this.notifyAll of the thread is called.

Let’s take A look at this application scenario: Suppose there are three employees A,B, and C in the company, and they have A meeting. But A needs to wait until B and C are ready to start, and B and C need to be ready at the same time. Let’s first simulate the above scenario with Join.

Employee.java:

public class Employee extends Thread{
        
	private String employeeName;
	
	private long time;

	public Employee(String employeeName,long time){
		this.employeeName = employeeName;
		this.time = time;
	}
	
	@Override
	public void run(a) {
		try {
			System.out.println(employeeName+ "Get ready.");
			Thread.sleep(time);
			System.out.println(employeeName+"Ready to go");
		} catch(Exception e) { e.printStackTrace(); }}}Copy the code

JoinTest.java:

public class JoinTest {

	public static void main(String[] args) throws InterruptedException {
		Employee a = new Employee("A".3000);
		Employee b = new Employee("B".3000);
		Employee c = new Employee("C".4000);
		
		b.start();
		c.start();
		
		b.join();
		c.join();
		System.out.println("B,C ready to go"); a.start(); }}Copy the code

The final output is as follows:

C Start Preparation B Start Preparation B Ready to finish C Ready to finish B,C Ready to finish A Start Preparation A Ready to finishCopy the code

As you can see,A is always executed after B and C are ready.

In CountDownLatch we use two main methods: one is await(), which blocks the thread calling it, and the other is countDown(), which decrement the counter by one. When the counter is 0, the thread blocked by calling await() will wake up. Continue execution.

Next, let’s use CountDownLatch to simulate this.

Employee.java:

public class Employee extends Thread{

	private String employeeName;
	
	private long time;
	
	private CountDownLatch countDownLatch;

	public Employee(String employeeName,long time, CountDownLatch countDownLatch){
		this.employeeName = employeeName;
		this.time = time;
		this.countDownLatch = countDownLatch;
	}
	
	@Override
	public void run(a) {
		try {
			System.out.println(employeeName+ "Get ready.");
			Thread.sleep(time);
			System.out.println(employeeName+"Ready to go");
			countDownLatch.countDown();
		} catch(Exception e) { e.printStackTrace(); }}}Copy the code

CountDownLatchTest.java:

public class CountDownLatchTest {
	public static void main(String[] args) throws InterruptedException {
		CountDownLatch countDownLatch = new CountDownLatch(2);
		Employee a = new Employee("A".3000,countDownLatch);
		Employee b = new Employee("B".3000,countDownLatch);
		Employee c = new Employee("C".4000,countDownLatch);
		
		b.start();
		c.start();
		countDownLatch.await();
		System.out.println("B,C ready to go"); a.start(); }}Copy the code

The following output is displayed:

B Ready TO finish C Ready to finish B,C Ready to finish A Ready to Finish A Ready to finishCopy the code

As you can see, both CountDownLatch and Join can simulate the above scenario. What’s the difference between them? Now let’s think about another situation and see the difference.

Suppose that the work of A, B, and C is divided into two phases, and A only needs to wait for B and C to complete the first phase of their work.

Let’s modify the Employee class:

public class Employee extends Thread{

	private String employeeName;
	
	private long time;
	
	private CountDownLatch countDownLatch;

	public Employee(String employeeName,long time, CountDownLatch countDownLatch){
		this.employeeName = employeeName;
		this.time = time;
		this.countDownLatch = countDownLatch;
	}
	
	@Override
	public void run(a) {
		try {
			System.out.println(employeeName+ "Phase one begins preparation.");
			Thread.sleep(time);
			System.out.println(employeeName+"Phase one is ready for completion.");
			
			countDownLatch.countDown();
			
			System.out.println(employeeName+ "Phase two begins preparation.");
			Thread.sleep(time);
			System.out.println(employeeName+"Phase two is ready for completion.");
			
		} catch(Exception e) { e.printStackTrace(); }}}Copy the code

The CountDownLatchTest class does not need to be modified.

B Phase 1 Preparations C Phase 1 Preparations B Phase 1 Preparations B Phase 2 Preparations C Phase 1 Preparations C Phase 2 Preparations B, Phase 1 Preparations A Phase 1 Preparations B Phase 2 Preparations A Phase 1 Preparations COMPLETE A Phase 2 start preparation C Phase 2 finish preparation A Phase 2 finish preparationCopy the code

It can be seen from the results that A starts to execute when the first stage of B and C is ready, without waiting for the second stage. In this scenario, join cannot be implemented.

Conclusion: Compared to the join method, which waits for thread to complete before continuing, CountDownLatch is more flexible and can implement more complex business scenarios by simply checking for a zero counter value.

Reference: blog.csdn.net/zhutulang/a…