Java并发包:CountDownLatch和CyclicBarrier
2016-07-07 11:41
615 查看
文章译自:http://tutorials.jenkov.com/java-util-concurrent/index.html
抽空翻译了一下这个教程的文章,后面会陆续放出,如有不妥,请批评指正。
转自请注明出处。
CountDownLatch初始化时需要给定一个总数。这个总数将会随着调用countDown()方法每次递减。通过调用await()方法,线程将会等到这个总数变为0。调用await()方法会阻塞线程直到那个总数递减到0为止。
下面是一个简单的例子。Decrementer在CountDownLatch上调用了countDown()3次之后,Waiter将会释放。
所有的线程会在CyclicBarrier上调用await()方法相互等待,一旦N个线程正在CyclicBarrier上等待,所有的线程都会释放并且继续执行。
有2个线程在CyclicBarrier上等待,这两个线程就会释放。
你也可以指定线程等待的时间。当等待的时间过了,即使不是所有指定的线程都在CyclicBarrier上等待,线程也会被释放。下面是如何指定超时时间:
等待的线程会在CyclicBarrier上等待直至:
最后的线程达到
线程被另一个线程中断(另一个线程调用interrupt()方法)
另一个等待的线程被中断
另一个等待的线程等待超时
某些外部线程调用了CyclicBarrier.reset()方法
下面是CyclicBarrier类:
下面是上面代码在控制台的输出结果,注意每次执行线程在控制台上打印的顺序也可能不一样。有时候可能是Thread-0先打印,有时候可能是Thread-1先打印。
抽空翻译了一下这个教程的文章,后面会陆续放出,如有不妥,请批评指正。
转自请注明出处。
CountDownLatch
java.util.concurrent.CountDownLatch是一种并发结构,它允许一个或者多个线程等待一个给定的操作集合完成。CountDownLatch初始化时需要给定一个总数。这个总数将会随着调用countDown()方法每次递减。通过调用await()方法,线程将会等到这个总数变为0。调用await()方法会阻塞线程直到那个总数递减到0为止。
下面是一个简单的例子。Decrementer在CountDownLatch上调用了countDown()3次之后,Waiter将会释放。
CountDownLatch latch = new CountDownLatch(3); Waiter waiter = new Waiter(latch); Decrementer decrementer = new Decrementer(latch); new Thread(waiter).start(); new Thread(decrementer).start(); Thread.sleep(4000);
public class Waiter implements Runnable{ CountDownLatch latch = null; public Waiter(CountDownLatch latch) { this.latch = latch; } public void run() { try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Waiter Released"); } }
public class Decrementer implements Runnable { CountDownLatch latch = null; public Decrementer(CountDownLatch latch) { this.latch = latch; } public void run() { try { Thread.sleep(1000); this.latch.countDown(); Thread.sleep(1000); this.latch.countDown(); Thread.sleep(1000); this.latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } }
CyclicBarrier
java.util.concurrent.CyclicBarrier类的同步机制可以通过某些算法实现同步线程的执行,换句话说,它就像一个屏障(或着说栏栅),在任何线程执行之前,所有线程必须在此处等着,直到所有线程都到达才执行。下面是图解:所有的线程会在CyclicBarrier上调用await()方法相互等待,一旦N个线程正在CyclicBarrier上等待,所有的线程都会释放并且继续执行。
创建 CyclicBarrier
当你创建一个CyclicBarrier,你需要指定在它上面有多少个体线程同时等待,下面是如何创建一个CyclicBarrier:CyclicBarrier barrier = new CyclicBarrier(2);
有2个线程在CyclicBarrier上等待,这两个线程就会释放。
在CyclicBarrier上等待
下面是一个线程如何在CyclicBarrier上等待:barrier.await();
你也可以指定线程等待的时间。当等待的时间过了,即使不是所有指定的线程都在CyclicBarrier上等待,线程也会被释放。下面是如何指定超时时间:
barrier.await(10, TimeUnit.SECONDS);
等待的线程会在CyclicBarrier上等待直至:
最后的线程达到
线程被另一个线程中断(另一个线程调用interrupt()方法)
另一个等待的线程被中断
另一个等待的线程等待超时
某些外部线程调用了CyclicBarrier.reset()方法
CyclicBarrier Action
CyclicBarrire支持一种栏栅行为,一但最后的线程达到时线程将会执行。Runnable的栅栏行为通过CyclicBarrier的构造函数传递,像下面这样:Runnable barrierAction = ... ; CyclicBarrier barrier = new CyclicBarrier(2, barrierAction);
CyclicBarrier示例
下面的代码展示如何使用CyclicBarrier:Runnable barrier1Action = new Runnable() { public void run() { System.out.println("BarrierAction 1 executed "); } }; Runnable barrier2Action = new Runnable() { public void run() { System.out.println("BarrierAction 2 executed "); } }; CyclicBarrier barrier1 = new CyclicBarrier(2, barrier1Action); CyclicBarrier barrier2 = new CyclicBarrier(2, barrier2Action); CyclicBarrierRunnable barrierRunnable1 = new CyclicBarrierRunnable(barrier1, barrier2); CyclicBarrierRunnable barrierRunnable2 = new CyclicBarrierRunnable(barrier1, barrier2); new Thread(barrierRunnable1).start(); new Thread(barrierRunnable2).start();
下面是CyclicBarrier类:
public class CyclicBarrierRunnable implements Runnable{ CyclicBarrier barrier1 = null; CyclicBarrier barrier2 = null; public CyclicBarrierRunnable( CyclicBarrier barrier1, CyclicBarrier barrier2) { this.barrier1 = barrier1; this.barrier2 = barrier2; } public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " waiting at barrier 1"); this.barrier1.await(); Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " waiting at barrier 2"); this.barrier2.await(); System.out.println(Thread.currentThread().getName() + " done!"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } }
下面是上面代码在控制台的输出结果,注意每次执行线程在控制台上打印的顺序也可能不一样。有时候可能是Thread-0先打印,有时候可能是Thread-1先打印。
Thread-0 waiting at barrier 1 Thread-1 waiting at barrier 1 BarrierAction 1 executed Thread-1 waiting at barrier 2 Thread-0 waiting at barrier 2 BarrierAction 2 executed Thread-0 done! Thread-1 done!
相关文章推荐
- java实现的读写锁
- Java类型擦除
- extjs4 表单提交到struts2 action 的响应问题
- 浅谈Java运行时数据区
- 解决webservice的WSDL文件无法转成java代码
- Java序列化(Serialization) 机制
- dubbo + spring boot
- 复习(java):语法:java基础库
- java反射概念加案例
- Myeclipse中文乱码问题
- Java IO工作机制分析
- 命令行运行java
- java中的boolean是否有默认值?
- 谈Java中的hashcode方法
- java nio(non-blocking io)简介及和io
- myBatis + SpringMVC上传、下载文件、显示byte图片文件、等比例缩放图片
- java class路径
- SPRING BOOT 配置大全
- eclipse生成boolean型变量的getter是is开头
- java list倒序输出及复制list集合