juc部分工具类使用-并发测试

1. 工具

1.1 CountDownLatch:线程等待

​ 比如在测试并发时,主线程需要等待其他线程执行完才退出就可以用CountDownLatch来实现了。

@Test
    public void testCountDown() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("开始执行,计数减一");
                    latch.countDown();
                    try {
                        Thread.sleep(1000);
                        latch.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("执行完毕");
                }
            }).start();
        }
        latch.await();
        Thread.sleep(2000);
        System.out.println("所有都执行完了");
    }

1.2 CyclicBarrier:栅栏,控制线程同时到达某个阶段

​ 比如需要控制线程同时做一些准备工作后,才同时进行接下来的操作,就能用到栅栏了。

@Test
    public void testCyclicBarrier() throws BrokenBarrierException, InterruptedException {
        CyclicBarrier barrier = new CyclicBarrier(6);
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("开始执行");
                    try {
                        Thread.sleep(1000);
                        // 等待其他线程执行到这一步
                        barrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                    // 后续执行操作
                    System.out.println("执行完毕");
                }
            }).start();
        }
        barrier.await();
        Thread.sleep(1000);
        System.out.println("结束");
    }

1.3 Phaser:多阶段栅栏

​ 比如有多个阶段的工作都需要进行控制,同时到达后才能触发,就可以用到这个了

@Test
    public void testPh() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);
        Phaser phaser = new Phaser(10){
            @Override
            protected boolean onAdvance(int phase, int registeredParties) {
                System.out.println("========phase:"+phase+"======");
                return registeredParties == 0;
            }
        };

        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("开始执行");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    phaser.arriveAndAwaitAdvance();
                    System.out.println("完成执行1");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    phaser.arriveAndAwaitAdvance();
                    System.out.println("完成执行2");
                    latch.countDown();
                }
            }).start();
        }
        latch.await();
        System.out.println("全部执行完");
    }

2. 实际使用

​ 有一个场景,需要测试并发场景捡瓶子时的性能,捡瓶子前需要先按概率抽取要捡哪个时间段的瓶子(准备工作),想要真正第模拟捡瓶子的性能,就需要控制所有线程能同时触发捡这个功能,而不是同时从概率抽取开始,所以就需要栅栏来控制了,概率抽取是第一个阶段的工作,捡瓶子是第二个阶段的工作,接下来才能让主线程结束。

2.1 CountDownLatch结合Phaser

CountDownLatch:通知主线程,测试线程已经完成操作了

Phaser:完成两个阶段的栅栏控制

@Test
    public void getRandomBottlePharse() throws InterruptedException, BrokenBarrierException {
        String userId = "88888";
        Phaser phaser = new Phaser(50){
            @Override
            protected boolean onAdvance(int phase, int registeredParties) {
                System.out.println("==============第"+phase+"阶段完成==============");
                return registeredParties == 0;
            }
        };
        CountDownLatch latch = new CountDownLatch(50);
        for (int i = 0; i < 50; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    CollectBottleRate collectBottleRate = new CollectBottleRate();
                    collectBottleRate.setLastDay(60);
                    collectBottleRate.setLastWeek(20);
                    collectBottleRate.setLastMonth(15);
                    collectBottleRate.setLastHalfYear(5);
                    int day = collectBottleRate.lotteryBottleDay();
                    System.out.println("等待所有线程准备,day:"+day+", count:" + phaser.getArrivedParties());
                    // 栅栏:等待准备
                    phaser.arriveAndAwaitAdvance();

                    Bottle b = randomBottle.getRandomBottle(userId, day);
                    System.out.println("捡到瓶子:" + b.toString());
                    // 主线程等待执行完
                    phaser.arriveAndAwaitAdvance();
                    latch.countDown();
                }
            }).start();
        }
        latch.await();
        System.out.println("全部执行完了");
    }

2.2 CountDownLatch结合CyclicBarrier

CountDownLatch:同样通知主线程测试线程的执行情况

CyclicBarrier:只对第一个阶段进行栅栏控制

@Test
    public void getRandomBottle() throws InterruptedException, BrokenBarrierException {
        String userId = "2088612750326750";
        CyclicBarrier barrier = new CyclicBarrier(50);
        CountDownLatch latch = new CountDownLatch(50);
        for (int i = 0; i < 50; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    CollectBottleRate collectBottleRate = new CollectBottleRate();
                    collectBottleRate.setLastDay(60);
                    collectBottleRate.setLastWeek(20);
                    collectBottleRate.setLastMonth(15);
                    collectBottleRate.setLastHalfYear(5);
                    int day = collectBottleRate.lotteryBottleDay();
                    System.out.println("等待所有线程准备, count:" + barrier.getNumberWaiting());
                    try {
                        // 栅栏:等待准备
                        barrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                    Bottle b = randomBottle.getRandomBottle(userId, day);
                    System.out.println("捡到瓶子:" + b.toString());
                    // 主线程等待执行完
                    latch.countDown();
                }
            }).start();
        }
        latch.await();
        System.out.println("全部执行完了");
    }

3. 参考链接

http://www.jasongj.com/java/thread_communication/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值