前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【java】CyclicBarrier

【java】CyclicBarrier

作者头像
Leetcode名企之路
发布2018-09-12 15:23:22
5060
发布2018-09-12 15:23:22
举报
文章被收录于专栏:Leetcode名企之路Leetcode名企之路

背景

前面我们举了一个例子,说明CountDownLatch闭锁的运用,本文我们讲解一下CyclicBarrier的运用,这两个经常被面试官放在一起问区别,实际上记住和理解我举的这两个例子就基本掌握了它们的区别。

CyclicBarrier(栅栏)

CyclicBarrier类似于闭锁,与闭锁的关键区别在于,闭锁用于等待事件(上次我们的例子中,主线程等待其他cache加载完成才继续执行,没加载完成就阻塞主线程),栅栏用于等待其他线程,其作用是让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。CountDownLatch倾向于一个线程等多个线程,CyclicBarrier倾向于多个线程互相等待。

栅栏的作用就类似于运动员赛跑时候的发令枪,裁判没打发令枪之前,谁也不准跑

应用:性能测试

考虑这么一个问题,现在要对你们线上的数据库做压测。你可能想到这么几步:

  1. 搭建和线上一样配置的机子;
  2. 模拟线上数据;
  3. 进行读写测试;
  4. 调整读写请求的比例进行测试;
  5. 观察I/O、MEM、CPU等指标;
  6. 观察主从节点备份情况。

第2步准备数据的是时候,你起了1w个线程去准备数据,但是load数据是需要时间的,这个时候如果有的线程先请求了数据库,有的线程后请求数据库,对于数据库的QPS就是 < 1w的,所以需要他们同时并发的去请求。在load数据这个阶段我们用CyclicBarrier去拦住他们,当所有的线程都load好数据之后,同时请求数据库,对数据库进行压测。

代码语言:javascript
复制
public class CyclicBarrierTest {
    private static CyclicBarrier cyclicBarrier;

    public static class PrepareReadDataThread extends Thread {
        private int id;

        PrepareReadDataThread(int id) {
            this.id = id;
        }

        public void run() {
            try {
                System.out.println("线程:" + this.id + " 可以读数据啦!");
                cyclicBarrier.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("所有任务完毕,继续处理其他任务... "+System.currentTimeMillis());
        }
    }

    public static class PrepareWriteDataThread extends Thread {
        private int id;

        PrepareWriteDataThread(int id) {
            this.id = id;
        }

        public void run() {
            try {
                Thread.sleep(3000);
                System.out.println("线程:" + this.id + " 可以load写数据完成!");
                cyclicBarrier.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("所有任务完毕,继续处理其他任务... "+System.currentTimeMillis());
        }
    }


    public static void main(String[] args) {
        cyclicBarrier = new CyclicBarrier(5, () -> System.out.println("测试开始!"));
        for (int i = 0; i < 5; i++) {
            new PrepareReadDataThread(i).start();
        }
        //重置一下
        cyclicBarrier.reset();

        for (int i = 0; i < 5; i++) {
            new PrepareWriteDataThread(i).start();
        }
    }
}

对比

1.CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()方法重置。所以CyclicBarrier能处理更为复杂的业务场景。例如,如果计算发生错误,可以重置计数器,并让线程重新执行一次

2.CyclicBarrier还提供其他有用的方法,比如getNumberWaiting方法可以获得Cyclic-Barrier阻塞的线程数量。isBroken()方法用来了解阻塞的线程是否被中断

3.CountDownLatch倾向于一个线程等多个线程,CyclicBarrier倾向于多个线程互相等待

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-09-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Leetcode名企之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • CyclicBarrier(栅栏)
  • 应用:性能测试
  • 对比
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档