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的线程是从原先屏障处等待的几个线程中选择了一个来执行。