多线程中CountDownLatch的含义以及和join的区别

任何线程,通常是应用程序的主线程,调用CountDownLatch.await()将等到计数达到零或被另一个线程中断。所有其他线程都需要CountDownLatch.countDown()在完成或准备好后通过调用来倒计时。

一旦计数达到零,等待线程就会继续。其中一个缺点/优点CountDownLatch是它不可重复使用:一旦计数达到零,就不能再使用CountDownLatch了。

 

使用CountDownLatch当一个线程(比如主线程),需要等待一个或多个线程来完成,才能继续处理。

CountDownLatchJava 中使用的典型示例是服务器端核心Java应用程序,它使用服务体系结构,其中多个服务由多个线程提供,并且应用程序无法在所有服务成功启动之前开始处理。

 

package CountDownLatch_6;

import java.util.concurrent.CountDownLatch;

public class Manager {
	public static void main(String[] args) throws InterruptedException {
		CountDownLatch latch=new CountDownLatch(2);
		MyDevTeam devTeam=new MyDevTeam(latch, "dev1");
		MyDevTeam devTeam2=new MyDevTeam(latch, "dev2");
		devTeam.start();
		devTeam2.start();
		latch.await();
		MyQATeam qa=new MyQATeam();
		qa.start();
	}
	
}
class MyDevTeam extends Thread{
	CountDownLatch latch;
	public MyDevTeam(CountDownLatch latch,String name ) {
		// TODO Auto-generated constructor stub
		super(name);
		this.latch=latch;
	}
	
	public void run(){
		System.out.println("任务分配给"+currentThread().getName());
		try {
			Thread.sleep(2000);
			System.out.println(currentThread().getName()+"开始执行");
			latch.countDown();
			
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("任务已经被"+currentThread().getName()+"执行完毕");
		
	}
}

class MyQATeam extends Thread{
	public void run(){
		System.out.println("任务分配给qa执行");

		
		System.out.println("qa完成该任务");
	}
}

执行结果:

任务分配给dev2
任务分配给dev1
dev2开始执行
任务已经被dev2执行完毕
dev1开始执行
任务已经被dev1执行完毕
任务分配给qa执行
qa完成该任务

JOIN的限制: 以上示例也可以通过JOIN实现,但JOIN不能在两种情况下使用:

  1. 当我们使用ExecutorService而不是Thread类来创建线程时。
  2. 修改以上示例,管理员希望在开发完成80%任务后立即将代码切换到QA团队。这意味着CountDownLatch允许我们修改可用于等待另一个线程进行部分执行的实现。

上述代码修改

public void run(){
		System.out.println("任务分配给"+currentThread().getName());
		try {
			Thread.sleep(2000);
			System.out.println(currentThread().getName()+"第一阶段任务完成");
			latch.countDown();
			Thread.sleep(2000);
			System.out.println(currentThread().getName()+"第二阶段任务完成");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("任务已经被"+currentThread().getName()+"执行完毕");
		
	}
}

执行结果:

任务分配给dev1
任务分配给dev2
dev2第一阶段任务完成
dev1第一阶段任务完成
任务分配给qa执行
qa完成该任务
dev1第二阶段任务完成
任务已经被dev1执行完毕
dev2第二阶段任务完成
任务已经被dev2执行完毕
 

由执行结果可知qa在第二阶段任务执行之前就已经执行,

这种场景下,用join是没法实现的。

总结:调用join方法需要等待thread执行完毕才能继续向下执行,而CountDownLatch只需要检查计数器的值为零就可以继续向下执行,相比之下,CountDownLatch更加灵活一些,可以实现一些更加复杂的业务场景。

猜你喜欢

转载自blog.csdn.net/faker____/article/details/82894643