并发工具类 : CyclicBarrier

CyclicBarrier

一、作用

  • CyclicBarrier是并发编程的工具类,当一组线程需要全部到达某一个屏障点之后,后续的操作才可以继续执行,就可以使用CyclicBarrier,比如我们有四个数据采集线程和一个数据分析线程,我们需要在四个采集线程完成采集之后,再执行数据分析线程,可以借助CyclicBarrier来实现

二、代码

  package com.intellif.mozping.concurrentutil.cyclicbarrierp;

import com.intellif.mozping.tools.SleepTools;

import java.util.concurrent.CyclicBarrier;

/**
 * @author by mozping
 * @Classname CyclicBarrierTest
 * @Description 通过CyclicBarrier工具让一组线程到达指定点之后,再执行其他的操作
 * 这里定义了MyWorkBeforeThread线程,表示任务前期处理,MyWorkAfterThread表示任务后期处理
 * 定义了3个前期处理线程,需要3个线程都到达某个点之后,MyWorkAfterThread线程才能继续处理
 * 观察现象发现,三个线程会在await处相互等待,到达后MyWorkAfterThread线程就会执行,
 * 这里的初始化参数new CyclicBarrier(3, new MyWorkAfterThread());3代表有三个线程需要到达屏障点,
 * MyWorkAfterThread表示到达屏障点后会执行的线程,这里注意如果是3个线程但是在主线程只创建了2个线程,
 * 那么屏障点的条件一直不能被满足,线程会在await处阻塞,MyWorkAfterThread线程一直不会被调用
 * @Date 2019/1/2 16:29
 */
public class CyclicBarrierTest {

    //3表示需要到达屏障点的线程数量,MyWorkAfterThread表示到达屏障点后需要执行的任务
    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new MyWorkAfterThread());


    private static class MyWorkBeforeThread extends Thread {
        @Override
        public void run() {
            System.out.println("业务Before线程 [" + Thread.currentThread().getName() + "] 处理业务...");
            //随机休眠10以内的时间
            try {
                SleepTools.randomSecond(10);
                System.out.println("到达屏障点的线程数:" + (cyclicBarrier.getNumberWaiting() + 1));
                cyclicBarrier.await();
                System.out.println("业务Before线程 [" + Thread.currentThread().getName() + "] 等待完毕..." + System.currentTimeMillis());
            } catch (Exception e) {
                e.printStackTrace();
            }
            SleepTools.randomSecond(10);
            System.out.println("业务Before线程 [" + Thread.currentThread().getName() + "] 处理其他的事情..." + System.currentTimeMillis());
        }
    }

    private static class MyWorkAfterThread extends Thread {
        @Override
        public void run() {
            System.out.println("业务After线程 [" + Thread.currentThread().getName() + "] 处理..." + System.currentTimeMillis());
        }
    }

    public static void main(String[] args) {
        for (int i = 1; i <= 3; i++) {
            new MyWorkBeforeThread().start();
        }
    }
}


三、Tips

  • cyclicBarrier初始化的时候会指定到达屏障点的线程数,如果实际线程数小于该数目,就会一直在屏障点阻塞下去。
  • 同样的await方法也可以指定超时时间,
  • cyclicBarrier.getNumberWaiting()获取当前已经到达屏障点的线程数量,比如有三个线程需要到达屏障点,第一个线程到达后,该方法返回的就是1
  • cyclicBarrier.reset:重置屏障

你可能感兴趣的:(并发编程)