倒计数器:CountDownLatch | 循环栅栏:CyclicBarrier
2017-08-13 15:25
405 查看
倒计数器:CountDownLatch
CountDownLatch从名字就可以看出其作用:初始化一个计数,然后每次递减,直至为0,然后触发一个动作。只有一个带参构造器:
public CountDownLatch(int count); 主要提供了以下方法:
主线程进入await()时,进入等待状态。然后当倒计数器为0时,触发唤醒操作,打印"Fire!"。
循环栅栏:CyclicBarrier
CyclicBarrier的用法和CountDownLatch非常类似,但是功能更加强大。它可以实现反复的倒计数的功能,例如有多级的状态检查就可以使用。提供了2个构造器:
public CyclicBarrier(int parties);
public CyclicBarrier(int parties, Runnable barrierAction); 第一个构造器创建了计数器为n的循环栅栏;第二个构造器在第一个的基础上增加了到达"栅栏"时,需要触发的动作(一个线程),系统会自动启动线程。
下面给出一个demo:
public class CyclicBarrierDemo {
public static class Soldier implements Runnable {
private String soldier;
private final CyclicBarrier cyclic;
public Soldier(String soldier, CyclicBarrier cyclic) {
this.soldier = soldier;
this.cyclic = cyclic;
}
@Override
public void run() {
try {
// 等待所有士兵到齐
cyclic.await();
doWork();
// 等待所有士兵完成工作
cyclic.await();
} catch (Exception e) {
e.printStackTrace();
}
}
void doWork() {
try {
Thread.sleep(Math.abs(new Random().nextInt() % 10000));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(soldier + ": 完成任务");
}
}
public static class BarrierRun implements Runnable {
boolean flag;
int N;
public BarrierRun(boolean flag, int n) {
this.flag = flag;
N = n;
}
@Override
public void run() {
if (flag) {
System.out.println( N + " 个士兵完成任务");
} else {
System.out.println( N + " 个士兵集合完毕");
flag = true;
}
}
}
public static void main(String[] args) {
final int N = 10;
Thread[] allSoldier = new Thread
;
boolean flag = false;
CyclicBarrier cyclic = new CyclicBarrier(N, new BarrierRun(flag, N));
System.out.println("集合队伍");
for (int i = 0; i < 9; i++) {
System.out.println("士兵" + i + "报到");
allSoldier[i] = new Thread(new Soldier("士兵" + i, cyclic));
allSoldier[i].start();
}
}
} 从上述代码可以看出,主线程中创建了一个大小为10的循环栅栏,并且传入了一个执行动作BarrierRun。此时,创建了10个Soldier对象,并且每个线程内部都调用了cyclic.await()。每一次await()的调用,都会触发计数器减1。当减为0时,触发BarrierRun运行。Soldier中有两个cyclic.await()操作,所以有2个栅栏。
上面代码,如果在主线程中的循环次数少于10,则永远到不了栅栏。
链接:http://moguhu.com/article/detail?articleId=30
CountDownLatch从名字就可以看出其作用:初始化一个计数,然后每次递减,直至为0,然后触发一个动作。只有一个带参构造器:
public CountDownLatch(int count); 主要提供了以下方法:
// 等待计数器为0 public void await() throws InterruptedException; // 等待计数器为0,增加超时限制 public boolean await(long timeout, TimeUnit unit) throws InterruptedException; // 计数器减1 public void countDown();CountDownLatch适合检查事件完成条件,都完成后触发一系列的动作。demo如下:
public class CountDownLatchDemo implements Runnable { static final CountDownLatch end = new CountDownLatch(10); static final CountDownLatchDemo demo = new CountDownLatchDemo(); @Override public void run() { try { // 模拟检查任务 Thread.sleep(new Random().nextInt(10) * 1000); System.out.println("check complete"); end.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) throws InterruptedException { ExecutorService exec = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { exec.submit(demo); } // 等待检查 end.await(); // 发射火箭 System.out.println("Fire!"); exec.shutdown(); } }
主线程进入await()时,进入等待状态。然后当倒计数器为0时,触发唤醒操作,打印"Fire!"。
循环栅栏:CyclicBarrier
CyclicBarrier的用法和CountDownLatch非常类似,但是功能更加强大。它可以实现反复的倒计数的功能,例如有多级的状态检查就可以使用。提供了2个构造器:
public CyclicBarrier(int parties);
public CyclicBarrier(int parties, Runnable barrierAction); 第一个构造器创建了计数器为n的循环栅栏;第二个构造器在第一个的基础上增加了到达"栅栏"时,需要触发的动作(一个线程),系统会自动启动线程。
下面给出一个demo:
public class CyclicBarrierDemo {
public static class Soldier implements Runnable {
private String soldier;
private final CyclicBarrier cyclic;
public Soldier(String soldier, CyclicBarrier cyclic) {
this.soldier = soldier;
this.cyclic = cyclic;
}
@Override
public void run() {
try {
// 等待所有士兵到齐
cyclic.await();
doWork();
// 等待所有士兵完成工作
cyclic.await();
} catch (Exception e) {
e.printStackTrace();
}
}
void doWork() {
try {
Thread.sleep(Math.abs(new Random().nextInt() % 10000));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(soldier + ": 完成任务");
}
}
public static class BarrierRun implements Runnable {
boolean flag;
int N;
public BarrierRun(boolean flag, int n) {
this.flag = flag;
N = n;
}
@Override
public void run() {
if (flag) {
System.out.println( N + " 个士兵完成任务");
} else {
System.out.println( N + " 个士兵集合完毕");
flag = true;
}
}
}
public static void main(String[] args) {
final int N = 10;
Thread[] allSoldier = new Thread
;
boolean flag = false;
CyclicBarrier cyclic = new CyclicBarrier(N, new BarrierRun(flag, N));
System.out.println("集合队伍");
for (int i = 0; i < 9; i++) {
System.out.println("士兵" + i + "报到");
allSoldier[i] = new Thread(new Soldier("士兵" + i, cyclic));
allSoldier[i].start();
}
}
} 从上述代码可以看出,主线程中创建了一个大小为10的循环栅栏,并且传入了一个执行动作BarrierRun。此时,创建了10个Soldier对象,并且每个线程内部都调用了cyclic.await()。每一次await()的调用,都会触发计数器减1。当减为0时,触发BarrierRun运行。Soldier中有两个cyclic.await()操作,所以有2个栅栏。
上面代码,如果在主线程中的循环次数少于10,则永远到不了栅栏。
链接:http://moguhu.com/article/detail?articleId=30
相关文章推荐
- Java多线程编程-(8)-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- Java多线程编程-(6)-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- 两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- 两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- 两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- 两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- 两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- 两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- 两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- 两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- 两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- 两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- 两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- 两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier
- [沧海拾遗]java并发之CountDownLatch、Semaphore和CyclicBarrier
- Java中的计数器CountDownLatch
- CountDownLatch的使用(倒计时计数器)
- Java CountDownLatch 和 CyclicBarrier
- java 多线程 day16 CountDownLatch 倒计时计数器
- java CountDownLatch 和 CyclicBarrier