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

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()来实现它的功能,代码如下:

package com.ld.task;

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CyclicBarrier;

/**
 * CyclicBarrier:放行条件由一组线程本身决定
 */
public class UseCyclicBarrier {
    //     static CyclicBarrier cyclicBarrier = new CyclicBarrier(6);
    //6个线程都执行到await()方法时,会先执行AfterWork()线程,AfterWork()线程执行完成后在继续向下执行。
    static CyclicBarrier cyclicBarrier = new CyclicBarrier(6, new AfterWork());
    //    List<String> threadNames = new ArrayList<>();
    static ConcurrentHashMap<String, Object> concurrentHashMap = new ConcurrentHashMap<>(); //线程安全的集合

    static class WorkTask implements Runnable {
        @Override
        public void run() {
            try {
                concurrentHashMap.put(Thread.currentThread().getName(), Thread.currentThread().getId());
                Random r = new Random();
                if (r.nextBoolean()) {
                    System.out.println("线程" + Thread.currentThread().getName() + "做点别的事情...");
                    Thread.sleep(2000);
                }
                System.out.println("线程" + Thread.currentThread().getName() + "进入等待状态...");
                cyclicBarrier.await();//线程运行到此处等待的数量达到设定的初始值后,就会自动向下进行。
                Thread.sleep(1000);
                System.out.println("线程" + Thread.currentThread().getName() + "开始向下执行...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }

    static class AfterWork implements Runnable {
        @Override
        public void run() {
            if (!concurrentHashMap.isEmpty()) {
                for (String name : concurrentHashMap.keySet()) {
                    System.out.println("AfterWork:" + name);
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 6; i++) {
//            Thread.sleep(1000);
            new Thread(new WorkTask()).start();
        }
    }
}

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

线程Thread-1进入等待状态...
线程Thread-0进入等待状态...
AfterWork:Thread-3
AfterWork:Thread-4
AfterWork:Thread-5
AfterWork:Thread-0
AfterWork:Thread-1
AfterWork:Thread-2
线程Thread-0开始向下执行...
线程Thread-3开始向下执行...
线程Thread-4开始向下执行...
线程Thread-5开始向下执行...
线程Thread-2开始向下执行...
线程Thread-1开始向下执行...
3、CyclicBarrier和CountDownLatch比较

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值