CyclicBarrier
1.运行原理图
假如有3个线程,内部运行时都使用了同一个CyclicBarrier,假如Thread1先到达屏障点,那么此时由于Thread2和Thread3还未到达,此时Thread1会等待;过了一会儿Thread2到达屏障点,此时Thread3还未到达,此时Thread2也会等待;最后,Thread3到达屏障点,发现Thread1和Thread2都到达了屏障点,此时Thread3会执行屏障动作(如果设置的话),然后唤醒Thread1和Thread2进入下一轮的执行。
2.实现原理:主要是用ReentrantLock来实现的,先到达屏障点的线程执行Condition.await方法,进行等待;最后到达屏障点的线程执行Condition.notifyAll方法唤醒所有的等待线程继续执行。
3.典型使用场景:让3个线程执行2轮然后退出执行的逻辑。
public class CyclicBarrierTest { /** * 屏障个数 */ private int barrierCount = 3; /** * 共执行的轮数 */ private int totalCount = 2; /** * 初始化一个屏障 */ private CyclicBarrier barrier = new CyclicBarrier(barrierCount,()->{ if(totalCount-- == 1){ doneFlag = true; System.out.println("执行完毕,退出屏障"); }else { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("第: " + (totalCount+1) + "轮执行结束"); } }); private volatile boolean doneFlag = false; class Task implements Runnable{ @Override public void run() { while (!doneFlag){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } try { int order = barrier.await(); System.out.println(Thread.currentThread().getName()+"第 "+ (totalCount+1) +" 轮执行结束,执行次序:"+(barrierCount-order) ); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } } } public void test(){ List<Thread> threads = new ArrayList<>(); for(int i=0;i<barrierCount;i++){ Thread thread = new Thread(new Task()); thread.start(); threads.add(thread); } //等待任务执行结束 for(Thread thread : threads){ try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("所有任务执行完毕"); } public static void main(String[] args){ new CyclicBarrierTest().test(); }
4.实际使用过程中要注意CyclicBarrier与CountDownLatch的区别,两者的主要区别是CyclicBarrier可以循环利用,而CountDownLatch不能够重复使用