多线程之倒计时器CountDownLatch和循环栅栏CyclicBarrier
1、倒计时器CountDownLatch
CountDownLatch是一个多线程控制工具类。通常用来控制线程等待,它可以让一个线程一直等待知道计时结束才开始执行
构造函数:
public CountDownLatch(int count) //count 计数个数
例如:在主线程中启动10个子线程去数据库中获取分页数据,需要等到所有线程数据都返回之后统一做统计处理
public class CountDownLatchDemo implements Runnable{
private static final CountDownLatch end = new CountDownLatch(10);
@Override
public void run() {
System.out.println("线程名称:" + Thread.currentThread().getName());
//数据业务处理
end.countDown();//计数减1
}
public static void main(String[] args) {
CountDownLatchDemo countDownLatchDemo = new CountDownLatchDemo();
System.out.println("计数开始");
for (int i = 0; i < 10; i++) {
new Thread(countDownLatchDemo).start();
}
try {
end.await();
System.out.println("计数结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
上述代码使用CountDownLatch的await()方法,要求主线程等待所有10个计数任务全部完成后,主线程才开始继续执行
可以通过getCount()方法获取当前的计数个数,当计数结束时count为0,且不会被重置
2、循环栅栏CyclicBarrier
CyclicBarrier也是一种多线程并发控制的工具。相比CountDownLatch,CyclicBarrier功能更加强大,主要表现在:
1)构造方法:
public CyclicBarrier(int parties, Runnable barrierAction)
CyclicBarrier的构造方法可以传入一个Runnable的barrierAction,可用于线程集结完毕后做一件特定的事情
2)CyclicBarrier可以重复使用,当一批线程凑满parties个是,计数器会归零,重新开始计数
public class CyclicBarrierDemo {
class Soldier implements Runnable{
private CyclicBarrier cyclicBarrier;
public Soldier(CyclicBarrier cyclicBarrier){
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
System.out.println("士兵 " + Thread.currentThread().getId() + " 报道");
try {
//等待所有士兵到齐
cyclicBarrier.await();
//执行任务
doWork();
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
private void doWork() throws InterruptedException {
Thread.sleep(1000);
System.out.println("士兵" + Thread.currentThread().getId()+ " 任务完成");
}
}
class Commond implements Runnable{
@Override
public void run() {
System.out.println("任务结束");
}
}
public static void main(String[] args) {
CyclicBarrierDemo cyclicBarrierDemo = new CyclicBarrierDemo();
CyclicBarrier cyclicBarrier = new CyclicBarrier(5, cyclicBarrierDemo.new Commond());
for (int i = 0; i < 20; i++) {
new Thread(cyclicBarrierDemo.new Soldier(cyclicBarrier)).start();
}
}
}
执行结果:
可以看到,线程被分成了5个一组