上一节介绍了CountDownLatch的使用,这一节,使用CyclicBarrier实现计算控制N个线程并发执行某个任务需要的时间。
CyclicBarrier 是 Java提供的一个同步工具类,屏障的意思是:当线程执行到被 CyclicBarrier.await()标记的屏障 处,会被阻塞,直到所有线程都到达屏障处,所有线程才会被释放,继续执行。
CyclicBarrier也有一个计数器,每标记一次await(),计数器减一。
但与 CountDownLatch 不同的是,CyclicBarrier提供了一个 reset() 方法,如果计数发生错误,可以重置计数器,并让线程重新执行一次。
而 CountDownLatch 的计数器,只能使用一次。
具体实现代码如下:
package com.myConcurrent.demo.concurrentUtils;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* @author fenghongyu
*/
public class CyclicBarrierDemo {
public void getRunTime(){
//线程准备阶段
int threadNum = 3;
//这里 + 1, 是为了让主线程控制其他被屏障挡住的线程启动。
CyclicBarrier startCyclicBarrier = new CyclicBarrier(threadNum + 1); //线程启动屏障
CyclicBarrier endCyclicBarrier = new CyclicBarrier(threadNum + 1); //线程终止屏障
for(int i=0;i<threadNum;i++) {
new Thread(() -> {
try {
//当前线程已到达屏障
startCyclicBarrier.await();
calcution(); //任务计算
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
} finally {
try {
endCyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}).start();
}
//线程准备完毕,准备启动
long startTime = System.nanoTime();
try {
startCyclicBarrier.await(); //主线程到达屏障,使得所有线程均到达屏障,启动其他等待线程
endCyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
long endTime = System.nanoTime();
System.out.println(endTime-startTime);
}
//某个计算任务
private void calcution() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
CyclicBarrierDemo cyclicBarrierDemo = new CyclicBarrierDemo();
cyclicBarrierDemo.getRunTime();
}
}