并发工具类:等待多线程完成的CountDownLatch,和join的区别

CountDownLatch

CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 

CountDownLatch用给定的计数初始化 CountDownLatch。调用countDown()方法,计数减1。在当前计数到达零之前,调用await()方法的线程会一直受阻塞。当前计数到达0之后,会释放所有等待的线程,调用await()的线程的后续调用都将继续执行。这种现象只出现一次,因为CountDownLatch没有提供任何机制去重新设置这个计数值。如果需要重置计数,请考虑使用 CyclicBarrier。 
CountDownLatch是一个通用同步工具,它有很多用途。将计数 1 初始化的 CountDownLatch 用作一个简单的开/关锁存器,或入口:在通过调用 countDown() 的线程打开入口前,所有调用 await()的线程都一直在入口处等待。用 N初始化的 CountDownLatch 可以使一个线程在 N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N 次之前一直等待。 

看下面的程序

 

public class CountDownLatchTest {
	
	public static void main(String[] args) throws InterruptedException {
		
		final CountDownLatch cl = new CountDownLatch(2);
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				cl.countDown();
				System.out.println("线程1唤醒");
			}
		}).start();
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(1000);
					cl.countDown();
					System.out.println("线程2唤醒");
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					System.out.println("次线程等待被唤醒");
					cl.await();
					System.out.println("次线程继续执行");
					
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
		
		System.out.println("主线程要等待被唤醒");
//		cl.await(400,TimeUnit.SECONDS);
		cl.await();
		System.out.println("主线程继续执行");
	}

}


 执行结果为:

 

 

主线程要等待被唤醒
次线程等待被唤醒
线程1唤醒
线程2唤醒
次线程继续执行
主线程继续执行

 

另外一个带指定时间的await方法,await(long time, TimeUnit unit): 如果计数还没到0,这个方法等待特定时间后,就会不再阻塞当前线程;如果计数到0了,等待时间还没到,当前线程仍然不再阻塞。

与join的区别

调用thread.join() 方法必须等thread 执行完毕,当前线程才能继续往下执行,而CountDownLatch通过计数器提供了更灵活的控制,只要检测到计数器为0当前线程就可以往下执行而不用 管相应的thread是否执行完毕。
看下面的程序:
public class JoinTest {
	public static void main(String[] args) {
		Thread a = new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("线程a执行结束");
				
			}
		});
		Thread b = new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("线程b执行结束");
				
			}
		});
		a.start();
		b.start();
		try {
			a.join();
			b.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("主线程结束");
	}

}

执行结果:
线程b执行结束
线程a执行结束
主线程结束
 
join用于让当前执行线程等待join线程执行结束。其实现原理是不停检查join线程是否存活,如果join线程存活则让当前线程wait,代码片段如下,wait(0)表示永远等待下去。
 
while (isAlive()) {
	 wait(0);
	}
直到join线程中止后,线程的this.notifyAll会被调用,调用notifyAll是在JVM里实现的,所以JDK里看不到
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值