what?
-
CountDownLatch是什么
CyclicBarrier是什么?
感性认识CountDownLatch
以工人和老板关系为例,老板等待所有工人干完活才开始检查
CountDownLatch示例代码
- worker代码
package concurrency.in.practice.countdownlatchtest;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* Created by haicheng.lhc on 19/07/2017.
*
* @author haicheng.lhc
* @date 2017/07/19
*/
public class Worker implements Runnable {
private CountDownLatch downLatch;
private String name;
public Worker(CountDownLatch downLatch, String name) {
this.downLatch = downLatch;
this.name = name;
}
public void run() {
this.doWork();
try {
TimeUnit.SECONDS.sleep(new Random().nextInt(10));
} catch (InterruptedException ie) {
}
System.out.println(this.name + "活干完了!");
this.downLatch.countDown();
}
private void doWork() {
System.out.println(this.name + "正在干活!");
}
}
- Boss代码
package concurrency.in.practice.countdownlatchtest;
import java.util.concurrent.CountDownLatch;
/**
* Created by haicheng.lhc on 19/07/2017.
*
* @author haicheng.lhc
* @date 2017/07/19
*/
public class Boss implements Runnable {
private CountDownLatch downLatch;
public Boss(CountDownLatch downLatch) {
this.downLatch = downLatch;
}
public void run() {
System.out.println("老板正在等所有的工人干完活......");
try {
this.downLatch.await();
} catch (InterruptedException e) {
}
System.out.println("工人活都干完了,老板开始检查了!");
}
}
- CountDownLatchDemo代码
package concurrency.in.practice.countdownlatchtest;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by haicheng.lhc on 19/07/2017.
*
* @author haicheng.lhc
* @date 2017/07/19
*/
public class CountDownLatchDemo {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
CountDownLatch latch = new CountDownLatch(3);
Worker w1 = new Worker(latch,"张三");
Worker w2 = new Worker(latch,"李四");
Worker w3 = new Worker(latch,"王二");
Boss boss = new Boss(latch);
executor.execute(w3);
executor.execute(w2);
executor.execute(w1);
executor.execute(boss);
executor.shutdown();
}
}
- 运行结果
CountDownLatch 使用场景
- 实现最大的并行性:有时我们想同时启动多个线程,实现最大程度的并行性。例如,我们想测试一个单例类。如果我们创建一个初始计数为1的CountDownLatch,并让所有线程都在这个锁上等待,那么我们可以很轻松地完成测试。我们只需调用 一次countDown()方法就可以让所有的等待线程同时恢复执行。
- 开始执行前等待n个线程完成各自任务:例如应用程序启动类要确保在处理用户请求前,所有N个外部系统已经启动和运行了。
- 死锁检测:一个非常方便的使用场景是,你可以使用n个线程访问共享资源,在每次测试阶段的线程数目是不同的,并尝试产生死锁。
感性认识CyclicBarrier
以所有室友都到齐了,每个人才可以点菜为例
- Roommate代码
package concurrency.in.practice.cyclicbarriertest;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* Created by haicheng.lhc on 19/07/2017.
*
* @author haicheng.lhc
* @date 2017/07/19
*/
public class Roommate implements Runnable {
private CyclicBarrier barrier;
private static int Count = 1;
private int id;
public Roommate(CyclicBarrier barrier) {
this.barrier = barrier;
this.id = Count++;
}
@Override
public void run() {
System.out.println(id + " : 我到了");
try {
//通知barrier,已经完成动作,在等待
barrier.await();
System.out.println("Id " + id + " : 点菜吧!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
- CyclicBarrierDemo代码
package concurrency.in.practice.cyclicbarriertest;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Created by haicheng.lhc on 19/07/2017.
*
* @author haicheng.lhc
* @date 2017/07/19
*/
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(5, new Runnable() {
//栅栏动作,在计数器为0的时候执行
@Override
public void run() {
System.out.println("我们都准备好了.");
}
});
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
es.execute(new Roommate(barrier));
}
}
}
- 测试结果
CyclicBarrier使用场景
CyclicBarrier可以用于多线程计算数据,最后合并计算结果的应用场景。比如我们用一个Excel保存了用户所有银行流水,每个Sheet保存一个帐户近一年的每笔银行流水,现在需要统计用户的日均银行流水,先用多线程处理每个sheet里的银行流水,都执行完之后,得到每个sheet的日均银行流水,最后,再用barrierAction用这些线程的计算结果,计算出整个Excel的日均银行流水。