并发工具类:等待多线程完成的CountDownLatch,和join的区别
2017-05-24 22:00
786 查看
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里看不到
相关文章推荐
- 并发工具类(一)等待多线程完成的CountDownLatch
- [Java并发]使用CountDownLatch和CyclicBarrier等待多线程完成
- 并发工具类CountDownLatch与CyclicBarrier的区别
- 用 join 或 CountDownLatch 让主线程等待所有子线程完成。
- 并发工具类(一)等待多线程完成的CountDownLatch
- Java并发工具类(一):等待多线程完成的CountDownLatch
- 一直被忽略的java 多线程并发工具类 CountDownLatch、Semaphore
- 多线程进阶之并发工具类:CountDownLatch、CyclicBarrier
- Java多线程等待所有线程结束(CountDownLatch/CyclicBarrier)
- Java并发之CountDownLatch 多功能同步工具类
- 多线程之CountDownLatch工具类
- 用CountDownLatch控制主线程等待所有多线程结束
- Java并发之 CAS + Thread.join / CountDownLatch 方式实现线程安全
- Java并发编程之——同步器工具类(semaphores, barriers, CountDownLatch,exchangers)
- java多线程 等待多个并发事件的完成
- 【Java多线程与并发库】14.java5的CountDownLatch同步工具
- 多线程计数器之CountDownLatch和join
- Java:多线程等待所有线程结束(CountDownLatch/CyclicBarrier) .
- Java:多线程等待所有线程结束(CountDownLatch/CyclicBarrier)
- CountDownLatch理解一:与join的区别