【问题标题】:CountDownLatch - understanding await and countDownCountDownLatch - 理解 await 和 countDown
【发布时间】:2012-03-23 03:02:22
【问题描述】:

根据 Javadoc: CountDownLatch 使用给定的计数进行初始化。 await 方法会一直阻塞,直到当前计数达到零。

这意味着在下面的代码中,因为我将 CountDownLatch 初始化为 1。一旦锁存器调用倒计时,所有线程都应该从它的 await 方法中解除阻塞。

但是,主线程正在等待所有线程完成。而且,我没有将主线程加入到其他线程的末尾。为什么主线程在等待?

    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.atomic.AtomicLong;

public class Sample implements Runnable {

    private CountDownLatch latch;

    public Sample(CountDownLatch latch)
    {
        this.latch = latch;
    }
    private static AtomicLong number = new AtomicLong(0);

    public long next() {
         return number.getAndIncrement();
    }

    public static void main(String[] args) {

        CountDownLatch latch = new CountDownLatch(1);
        for (int threadNo = 0; threadNo < 4000; threadNo++) {
          Runnable t = new Sample(latch);
          new Thread(t).start();
        }
        try {
            latch.countDown();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            latch.await();
            Thread.sleep(100);
            System.out.println("Count:"+next());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

【问题讨论】:

    标签: java concurrency java.util.concurrent


    【解决方案1】:

    尝试运行您的代码的以下修改版本:

    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.atomic.AtomicLong;
    
    public class Test implements Runnable {
    
        private CountDownLatch latch;
    
        public Test(CountDownLatch latch)
        {
            this.latch = latch;
        }
        private static AtomicLong number = new AtomicLong(0);
    
        public long next() {
             return number.getAndIncrement();
        }
    
        public static void main(String[] args) {
    
            CountDownLatch latch = new CountDownLatch(1);
            for (int threadNo = 0; threadNo < 1000; threadNo++) {
              Runnable t = new Test(latch);
              new Thread(t).start();
            }
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println( "done" );
        }
    
        @Override
        public void run() {
            try {
                Thread.sleep(1000 + (int) ( Math.random() * 3000 ));
                System.out.println(next());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                latch.countDown();
            }
        }
    
    }
    

    您应该会看到如下内容:

    0
    完成
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    这表明主线程实际上在第一个线程调用latch.countDown() 之后解除了对latch.await() 调用的阻塞

    【讨论】:

      【解决方案2】:

      您正在启动 4000 个线程,它们只等待 100 毫秒。你很可能压倒了盒子(所有线程将在大致相同的时间结束)。在您的线程开始外观中添加一个睡眠,并尝试增加超时以使其按预期工作。

      【讨论】:

      • 我在睡眠调用中添加了一些随机性:Thread.sleep(1000 + (int) ( Math.random() * 3000 ));latch.await() 之后的打印语句,一切都按预期工作
      • 我已经改变了实现,你能回答为什么会这样吗?为什么主线程等待所有线程完成?我没有加入任何连接要求主线程等到所有线程完成。
      • 在使用倒计时锁存器时,我们需要考虑两件事 - 1.您在一行代码中阻塞 N 个线程/任务,thread.await 2.您必须有一个唤醒每个线程的标准等待并记住唤醒可以由其他线程完成,因为其余线程正在等待!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-11
      • 2012-05-06
      • 2019-03-04
      • 2018-10-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多