CyclicBarrier是一个同步工具类
作用:它允许一组线程之间互相等待,直到最后一个线程到达屏障后,所有线程继续执行。
原理:通过一个计数器实现,计数器的初始化值等于线程数量。当一个线程到达屏障后,计数器减一。当计数器为0时,屏障打开,所有线程继续执行。
主要涉及方法:await() 让线程等待,并将计数器减一
举例:假设有4个工作线程,代码如下
public class UseCyclicBarrier {
private static CyclicBarrier barrier = new CyclicBarrier(4);//计数器设置为4
//工作线程
private static class SubThread implements Runnable{
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getId()+"工作线程,进行工作");
barrier.await();//到达屏障,线程进行等待
System.out.println(Thread.currentThread().getId()+"工作线程,其他业务");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
for(int i=0;i<=3;i++){
Thread thread = new Thread(new SubThread());
thread.start();
}
}
}
在主线程中我们调用了四个工作线程,当这四个工作线程运行到barrier.await();时就会进行等待,直到最后一个线程也到达后,所有线程继续执行,运行结果如下:
同样是并发工具类,CyclicBarrier和CountDownLatch有什么区别呢?
一、CountDownLatch的放行条件是外部线程控制,而CyclicBarrier的放行条件是该组线程自己控制,即最后一个线程到达屏障
二、CountDownLatch计数器大于等于线程数,而CyclicBarrier计数器等于线程数
三、CountDownLatch计数器减一需要手动调用countDown(),而CyclicBarrier的await()中自带减一
四、CyclicBarrier的构造函数,可初始化计数器值的同时传入一个Runnable参数,当屏障打开后,自动调用该线程。即CyclicBarrier(int parties, Runnable barrierAction)
还是上面那个例子,加入一个Runnable参数
public class UseCyclicBarrier {
private static CyclicBarrier barrier
= new CyclicBarrier(4,new CollectThread());//初始化计数器值,以及传入一个Runnable参数
//负责屏障开放以后的工作
private static class CollectThread implements Runnable{
@Override
public void run() {
System.out.println("屏障打开后自动调用本线程");
}
}
//工作线程
private static class SubThread implements Runnable{
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getId()+"工作线程,进行工作");
barrier.await();//到达屏障,线程进行等待
System.out.println(Thread.currentThread().getId()+"工作线程,其他业务");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
for(int i=0;i<=3;i++){
Thread thread = new Thread(new SubThread());
thread.start();
}
}
}
执行结果如下