线程的并发工具类(3)---CyclicBarrier

朱雀 2023-05-28 15:45 342阅读 0赞

CyclicBarrier的用法

        • 1、CyclicBarrier介绍
            • 1.1、用法场景
            • 1.2、原理
        • 2、CyclicBarrier实例
        • 3、CyclicBarrier和CountDownLatch比较

1、CyclicBarrier介绍

CyclicBarrier,线程的同步工具类。

作用:让一组线程达到某个屏障,被阻塞,一直到组内最后一个线程达到屏障时,屏障开放,所有被阻塞的线程会继续运行。由自身(该组线程本身)去控制。

1.1、用法场景

实现多个线程的最大并行性。就像生活中我们会约朋友们到某个餐厅一起吃饭,有些朋友可能会早到,有些朋友可能会晚到,但是这个餐厅规定必须等到所有人到齐之后才会让我们进去。(由这组线程本身控制)

1.2、原理

在初始化CyclicBarrier实例的时候,使用new CyclicBarrier(N)初始化计数器为N。工作线程调用await()方法进行等待,等待N个线程都到达await()这里时,屏障开放,向下执行。如果初始化计数器使用new CyclicBarrier(N,new ThreadAfterWork()),则当N个线程都到达await()这里,屏障开放,会先依次执行ThreadAfterWork()这个线程实例。当所有的线程执行完ThreadAfterWork子线程后再继续向下执行。

2、CyclicBarrier实例

CyclicBarrier中主要使用了await()来实现它的功能,代码如下:

  1. package com.ld.task;
  2. import java.util.Random;
  3. import java.util.concurrent.BrokenBarrierException;
  4. import java.util.concurrent.ConcurrentHashMap;
  5. import java.util.concurrent.CyclicBarrier;
  6. /** * CyclicBarrier:放行条件由一组线程本身决定 */
  7. public class UseCyclicBarrier {
  8. // static CyclicBarrier cyclicBarrier = new CyclicBarrier(6);
  9. //6个线程都执行到await()方法时,会先执行AfterWork()线程,AfterWork()线程执行完成后在继续向下执行。
  10. static CyclicBarrier cyclicBarrier = new CyclicBarrier(6, new AfterWork());
  11. // List<String> threadNames = new ArrayList<>();
  12. static ConcurrentHashMap<String, Object> concurrentHashMap = new ConcurrentHashMap<>(); //线程安全的集合
  13. static class WorkTask implements Runnable {
  14. @Override
  15. public void run() {
  16. try {
  17. concurrentHashMap.put(Thread.currentThread().getName(), Thread.currentThread().getId());
  18. Random r = new Random();
  19. if (r.nextBoolean()) {
  20. System.out.println("线程" + Thread.currentThread().getName() + "做点别的事情...");
  21. Thread.sleep(2000);
  22. }
  23. System.out.println("线程" + Thread.currentThread().getName() + "进入等待状态...");
  24. cyclicBarrier.await();//线程运行到此处等待的数量达到设定的初始值后,就会自动向下进行。
  25. Thread.sleep(1000);
  26. System.out.println("线程" + Thread.currentThread().getName() + "开始向下执行...");
  27. } catch (InterruptedException e) {
  28. e.printStackTrace();
  29. } catch (BrokenBarrierException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. }
  34. static class AfterWork implements Runnable {
  35. @Override
  36. public void run() {
  37. if (!concurrentHashMap.isEmpty()) {
  38. for (String name : concurrentHashMap.keySet()) {
  39. System.out.println("AfterWork:" + name);
  40. }
  41. }
  42. }
  43. }
  44. public static void main(String[] args) throws InterruptedException {
  45. for (int i = 0; i < 6; i++) {
  46. // Thread.sleep(1000);
  47. new Thread(new WorkTask()).start();
  48. }
  49. }
  50. }

上面的CyclicBarrier实例中计数器初始化为6,并且设定了一个子线程去处理别的业务。首先将循环启动6次线程实例,当6个线程都执行到await()方式的时候,屏障开放,6个线程分别会首先执行AfterWork()子线程,等待6个AfterWork()子线程都执行完成后,才会继续向下执行。
运行结果:

  1. 线程Thread-1进入等待状态...
  2. 线程Thread-0进入等待状态...
  3. AfterWork:Thread-3
  4. AfterWork:Thread-4
  5. AfterWork:Thread-5
  6. AfterWork:Thread-0
  7. AfterWork:Thread-1
  8. AfterWork:Thread-2
  9. 线程Thread-0开始向下执行...
  10. 线程Thread-3开始向下执行...
  11. 线程Thread-4开始向下执行...
  12. 线程Thread-5开始向下执行...
  13. 线程Thread-2开始向下执行...
  14. 线程Thread-1开始向下执行...

3、CyclicBarrier和CountDownLatch比较

1、CountDownLatch放行由第三者控制,CyclicBarrier放行由一组线程本身控制
2、CountDownLatch放行条件》=线程数,CyclicBarrier放行条件=线程数

发表评论

表情:
评论列表 (有 0 条评论,342人围观)

还没有评论,来说两句吧...

相关阅读

    相关 线并发工具

    Fork-Join 什么是分而治之? 规模为N的问题,N<阈值,直接解决,N>阈值,将N分解为K个小规模子问题,子问题互相对立,与原问题形式相同,将子问题的解合并得到