在java1.5中引入了并发工具类CountDownLatch、CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue,都在java.util.concurrent包下。在这里简要介绍一下CountDownLatch,其是Java并发编程中较为重要的工具类。
CountDownLatch能够让一个线程或多个线程等待其他线程完成各自任务后再执行,是JDK 5中闭锁的一个实现。
1.什么是闭锁(Latch)?
闭锁(Latch)是一种同步方法,可以延迟线程的进度,直到此线程到达一个终点状态。就如同锁上的一扇大门,当锁打开时,所有线程都被阻塞,一旦锁被打开,所有线程均将执行,同时这个闭锁状态就失效,并且不可恢复。因此,闭锁时一次性的,所有特定活动均需要在闭锁打开之后才能完成。
2.CountDownLatch如何实现?
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量,每当一个线程完成了自己的任务,计数器的值就会减少1。当计数器值到达0时,即所有线程任务均已完成,在闭锁上等待的线程就可以恢复执行了。
3.CountDownLatch如何使用?
CountDownLatch构造方法:
public CountDownLatch(int count);
CountDownLatch重要的三个方法:
// 挂起
public void await() throws InterruptedException;
// 挂起指定时间
public boolean await(long timeout, TimeUnit unit) throws InterruptedException;
// 计数器减1
public void countDown();
CountDownLatch工作流程如下:
主线程启动-->创建N个线程的CountDownLatch-->主线程等待闭锁-->N个线程完成-->主线程恢复运行
示例:
// 声明闭锁对象
final CountDownLatch latch = new CountDownLatch(threadNum);
new Thread() {
public void run() {
// 线程1执行体
// 闭锁计数器减1
latch.countDown();
}
}.start();
new Thread() {
public void run() {
// 线程2执行体
// 闭锁计数器减1
latch.countDown();
}
}.start();
// 闭锁等待
latch.await();
// 主线程恢复执行
// TODO
CyclicBarrier用法
CyclicBarrier就如同同一个栅栏一样,可以控制多个线程都到达一个状态后,再执行下一步任务,Cyclic循环指的是在这些线程完成后,CyclicBarrier可以再次使用。
构造方法:
// parties个线程都到达一个状态后,执行barrierAction
public CyclicBarrier(int parties, Runnable barrierAction);
// 指定parties个线程到达一个状态
public CyclicBarrier(int parties);
重要方法:
// 等待所有线程都到达指定状态
public int await() throws InterruptedException, BrokenBarrierException;
// 等待指定时间
public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException;
示例:
如果有几个线程进行数据操作,并且需要所有线程都完成数据操作后,这些线程才能继续做后面的事,就可以利用CyclicBarrier
CyclicBarrier barrier = new CyclicBarrier(ThreadNum, callable);
// 线程1,2,3,4,...
new Thread(barrier) {
private CyclicBarrier cyclicBarrier;
public Thread(CyclicBarrier barrier) {
this.cyclicBarrier = barrier;
}
public void run() {
// 线程执行体
// 等待其他线程到达此状态
this.cyclicBarrier.await();
}
}