CountDownLatch 俗稱閉鎖 構造函數中可以傳遞一個count 非負的整數值的數字,表示計數值,當這個計數值減到爲0時,才能繼續執行,比如說計算幾個線程執行消耗時間 。CyclicBarrier 俗稱同步屏障,它的構造函數有兩種,其他一個也是傳遞一個非負的整數值,表示幾個線程需要達到屏障處,另一個構造函數除了那個非零的整數值,還可以傳遞一個Runnable接口的參數,可以在都達到屏障處後在執行一個Runnable接口的實現。旨在所有的線程都達到了一個屏障的時候,再執行後續的操作。已計算線程的運行時間來說,我們可以嘗試用CountDownLatch,CyclicBarrier及join來試試看。
public class TestCountDownLatchAndCyclicBarrier {
public static void main(String[] args) {
CountDownLatch cdl = new CountDownLatch(3);
TwoUseDemo ldtest = new TwoUseDemo(cdl);
Instant start_0 = Instant.now();
for(int i = 0;i<3;i++){
new Thread(()->ldtest.testCountDownLatch(),"ldtest_"+i).start();
}
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 耗費時間爲>>>>>>>>"+Duration.between(start_0, Instant.now()));
Instant start_1 = Instant.now();
CyclicBarrier cb = new CyclicBarrier(3, new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" 耗費時間>>>>>>>>"+Duration.between(start_1, Instant.now()));
}
});
TwoUseDemo cbtest = new TwoUseDemo(cb);
for(int i = 0;i<3;i++){
new Thread(()->cbtest.testCyclicBarrier(),"cbtest_"+i).start();
}
TwoUseDemo blankTest = new TwoUseDemo();
Instant start_2 = Instant.now();
List<Thread> threads = new ArrayList<>();
IntStream.range(0, 3).forEach((i)->{
threads.add(new Thread(()->{
blankTest.blank();
},"blank_"+i));
});
threads.stream().forEach((t)->{
t.start();
try {
t.join();
} catch (Exception e) {
e.printStackTrace();
}
});
System.out.println(Thread.currentThread().getName()+" 耗費時間爲>>>>>>>>"+Duration.between(start_2, Instant.now()));
}
}
class TwoUseDemo{
private CountDownLatch latch;
private CyclicBarrier cb;
public TwoUseDemo(){
}
public TwoUseDemo(CountDownLatch latch){
this.latch = latch;
}
public TwoUseDemo(CyclicBarrier cb){
this.cb = cb;
}
public void testCountDownLatch(){
for(int i = 0;i<6;i++){
if(i%2==0){
System.out.println(Thread.currentThread().getName()+">>>>>>>>>>>>>>>"+i);
}
}
latch.countDown();
}
public void testCyclicBarrier(){
for(int i = 0;i<6;i++){
if(i%2==0){
System.out.println(Thread.currentThread().getName()+">>>>>>>>>>>>>>>"+i);
}
}
try {
cb.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
public void blank(){
for(int i = 0;i<6;i++){
if(i%2==0){
System.out.println(Thread.currentThread().getName()+">>>>>>>>>>>>>>>"+i);
}
}
}
}
控制檯運行結果如下
有點特別的地方是 CyclicBarrier 中的最後執行Runnable的線程是從原先屏障處等待的幾個線程中選擇了一個來執行。