使用CountDownLatch模拟并发

我们有时会使用java循环模拟并发请求,但for循环的实际情况是完成上一次循环后才进入本次循环,不同请求之间还是有细微的时间差,无法真正模拟出同时请求的场景。
我们把并发场景比作百米赛跑。现在假如有八名运动员参加百米赛,正常情况下裁判会等所有选手准备就绪后,扣响发令枪,所有运动员一起出发。我们以for循环来实现这一场景。

public class ForTestThread extends Thread {
    public static void main(String[] args) {
        for(int i = 1 ; i <= 8 ;i ++ ){
            Thread thread = new ForTestThread(i);
            thread.start();
        }
    }
    private int num;
    public ForTestThread(int num) {
        this.num = num;
    }
    @Override
    public void run() {
        System.out.println("第"+num+"个选手已就位");
        System.out.println("第"+num+"个选手已出发");
    }
}

输出的结果为

可以看到实际是每个运动员准备好之后就出发了,不会等所有运动员就位,这样每个运动员的出发时间是不同的,并不能实现模拟并发的初衷。

为了模拟真正意义的并发,我们可以使用JDK提供的CountDownLatch实现,使用了CountDownLatch的代码如下
 

import java.util.concurrent.CountDownLatch;
public class TestThread extends Thread {
    public static void main(String[] args) {
        final CountDownLatch latch = new CountDownLatch(10);
        for(int i = 1 ; i <= 10 ;i ++ ){
            Thread thread = new TestThread(latch,i);
            thread.start();
        }
    }
    private CountDownLatch latch;
    private int num;
    public TestThread(CountDownLatch latch,int num) {
        this.latch = latch;
        this.num = num;
    }
    @Override
    public void run() {
        latch.countDown();
        System.out.println("第"+num+"个选手已就位");
        try {
            latch.await();
            System.out.println("第"+num+"个选手已出发");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出结果

可以看到所有运动员是在全部运动员就位之后才出发的,虽然打印出的内容看起来所有出发的运动员分了先后,但实际上所有的出发操作是在同一时间产生的。

代码中用到的countDown和await方法是CountDownLatch最重要的两个方法,可以把CountDownLatch比作是一个发令枪命令,在声明CountDownLatch时会传入一个int类型的参数,这个参数是倒计数的开始,每调一次countDown,倒计数减一,当倒计数减大于0时执行await方法代码会停止到当前行,等倒计数减为0时所有所有停止的代码会同时往后执行。

发布了56 篇原创文章 · 获赞 67 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/leo187/article/details/98509472