浅谈jdk中CyclicBarrier和CountDownLatch的用法
CountDownLatch位于java.util.concurrent包下,是一个同步的辅助类,允许一个或多个线程等待直到其他线程完成操作。主要方法如下:
public void await() throws InterruptedException {}
public void countDown() {}
await方法是进行等待,countDown方法将计数减1,await是阻塞操作,计数不为0时一直阻塞,计数值由构造器传入。看下面完整例子:
package com.hzth.myapp.thread;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
int jobs = 3;
CountDownLatch cdl = new CountDownLatch(jobs);
System.out.println("开始分配任务。。。");
for (int i = 0; i < jobs; i++) {
new Worker(cdl).start();
}
System.out.println("等待完成任务。。。");
// 等待计数为0
cdl.await();
System.out.println("任务已经全部完成。。。");
}
static class Worker extends Thread {
CountDownLatch cdl = null;
public Worker(CountDownLatch cdl) {
this.cdl = cdl;
}
public void run() {
System.out.println("Thread:" + Thread.currentThread().getName() + " is doing job ... ");
try {
Thread.sleep(3000 + new Random().nextInt(5000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread:" + Thread.currentThread().getName() + " finished job ");
// 计数减1
cdl.countDown();
}
}
}
CyclicBarrier类提供的功能类似,像栅栏一样阻止通过,当全部到位之后才放行。主要方法如下:
public int await() throws InterruptedException, BrokenBarrierException {}
await方法是一个阻塞的方法,只有await方法调用次数达到指定次数时才返回,指定次数在构造函数中指定,构造方法中的Runnable会在其他线程await返回之后执行,看下面完整的例子:
package com.hzth.myapp.thread;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
public static void main(String[] args) {
int jobs = 4;
CyclicBarrier cyclicBarrier = new CyclicBarrier(4, new Runnable() {
@Override
public void run() {
System.out.println("所有任务已完成,开始退出。。。");
}
});
System.out.println("开始分配任务。。。");
for (int i = 0; i < jobs; i++) {
new Worker(cyclicBarrier).start();
}
System.out.println("任务已分配完。。。");
}
static class Worker extends Thread {
private CyclicBarrier cyclicBarrier;
public Worker(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
System.out.println("Thread:" + Thread.currentThread().getName() + " is doing job ... ");
try {
Thread.sleep(3000 + new Random().nextInt(5000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread:" + Thread.currentThread().getName() + " finished job,wait other worker ... ");
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println("Thread:" + Thread.currentThread().getName() + " exit ... ");
}
}
}
CountDownLatch和CyclicBarrier都能实现线程之间的等待,只是侧重点不同:
CountDownLatch侧重某个线程A等待其他线程执行完之后执行,CyclicBarrier侧重一组线程互相等待至某状态,再同时执行,另外CyclicBarrier可以重用。