上一節(jié)介紹了CountDownLatch的使用,這一節(jié),使用CyclicBarrier實(shí)現(xiàn)計(jì)算控制N個(gè)線程并發(fā)執(zhí)行某個(gè)任務(wù)需要的時(shí)間。
CyclicBarrier 是 Java提供的一個(gè)同步工具類,屏障的意思是:當(dāng)線程執(zhí)行到被 CyclicBarrier.await()標(biāo)記的屏障 處,會(huì)被阻塞,直到所有線程都到達(dá)屏障處,所有線程才會(huì)被釋放,繼續(xù)執(zhí)行。
CyclicBarrier也有一個(gè)計(jì)數(shù)器,每標(biāo)記一次await(),計(jì)數(shù)器減一。
但與 CountDownLatch 不同的是,CyclicBarrier提供了一個(gè) reset() 方法,如果計(jì)數(shù)發(fā)生錯(cuò)誤,可以重置計(jì)數(shù)器,并讓線程重新執(zhí)行一次。
而 CountDownLatch 的計(jì)數(shù)器,只能使用一次。
具體實(shí)現(xiàn)代碼如下:
package com.myConcurrent.demo.concurrentUtils;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* @author fenghongyu
*/
public class CyclicBarrierDemo {
public void getRunTime(){
//線程準(zhǔn)備階段
int threadNum = 3;
//這里 + 1, 是為了讓主線程控制其他被屏障擋住的線程啟動(dòng)。
CyclicBarrier startCyclicBarrier = new CyclicBarrier(threadNum + 1); //線程啟動(dòng)屏障
CyclicBarrier endCyclicBarrier = new CyclicBarrier(threadNum + 1); //線程終止屏障
for(int i=0;i<threadNum;i++) {
new Thread(() -> {
try {
//當(dāng)前線程已到達(dá)屏障
startCyclicBarrier.await();
calcution(); //任務(wù)計(jì)算
} 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();
}
//線程準(zhǔn)備完畢,準(zhǔn)備啟動(dòng)
long startTime = System.nanoTime();
try {
startCyclicBarrier.await(); //主線程到達(dá)屏障,使得所有線程均到達(dá)屏障,啟動(dòng)其他等待線程
endCyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
long endTime = System.nanoTime();
System.out.println(endTime-startTime);
}
//某個(gè)計(jì)算任務(wù)
private void calcution() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
CyclicBarrierDemo cyclicBarrierDemo = new CyclicBarrierDemo();
cyclicBarrierDemo.getRunTime();
}
}