CountDownLatch
简述
相当一个计数器,初始化的时候,我们给他一个初始计数值,假设是N,然后,任意一个线程都可以调用这个CountDownLatch的countDown(),一旦调用,这个计数器里面的计数N就会被自动减1,并且判断是否为0 ,如果不是零,这个线程就被阻塞住,等待其他线程调用countDown()方法,反之,如果调用完了之后是0,那么此时所有阻塞在countDown()的线程将会自动往下继续执行。典型的代码
实现代码
public static void main(String[] args) throws InterruptedException {
CountDownLatch cdl = new CountDownLatch(5);
for(var i=0;i<4;i++){
var t=new Thread(()->{
//信号值减少1
try {
System.out.println("thread"+Thread.currentThread().getName()+"count down");
Thread.sleep(1000);
cdl.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
cdl.countDown();
});
t.start();
}
cdl.countDown();
//如果线程存在着等待时间过久的嫌疑,我们可以设置等待固定的时间后就不再继续等待
// cdl.await(100, TimeUnit.MILLISECONDS);
System.out.println("program finish");
}
无论怎么执行,程序都能够保证5个线程的完整执行。
CyclicBarrier 屏障
简述
其实这个CyclicBarrier 与CountDownLatch一样,只不过,CyclicBarrier拥有reset的功能,它能够把其类内部维护的变量进行重置,也就是恢复到一开始的状态,方便重复的利用。
示例代码
public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
//允许多个线程一直等待等待直到其他线程执行完毕才开始执行
//信号量减少1
var barrier=new CyclicBarrier(6);
for(int i=0;i<5;i++) {
var t=new Thread(()->{
try {
Thread ct = Thread.currentThread();
System.out.println("thread:"+ct.getName());
Thread.sleep(100);
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
t.start();
}
barrier.await();
System.out.println("第一次屏障结束");
barrier.reset();
for(int i=0;i<5;i++) {
var t=new Thread(()->{
try {
Thread ct = Thread.currentThread();
System.out.println("thread:"+ct.getName());
Thread.sleep(100);
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
t.start();
}
barrier.await();
System.out.println("第二次屏障结束");
}