为什么java中的Countdownlatch不会停止在给定的锁存计数?

时间:2018-05-31 15:39:38

标签: java countdownlatch

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class Processor implements Runnable {
    private CountDownLatch latch;

    public Processor(CountDownLatch latch) {
        this.latch = latch;
    }

    public void run() {
        System.out.println("Started.");

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        latch.countDown();
    }
}
// -----------------------------------------------------

public class App {

    public static void main(String[] args) {

        CountDownLatch latch = new CountDownLatch(5); // coundown from 5 to 0

        ExecutorService executor = Executors.newFixedThreadPool(2); // 2 Threads in pool

        for(int i=0; i < 10; i++) {
            executor.submit(new Processor(latch)); // ref to latch. each time call new Processes latch will count down by 1
        }

        try {
            latch.await();  // wait until latch counted down to 0
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Completed.");
    }

}

输出:

发起者 入门 入门 入门 入门 入门 入门 Completed` 入门 入门 开始

在上面的代码中,“完成”应该在“开始”6次后打印,因为锁存计数降低到5 - 0,为什么它总是第7或第8次?我明白了吗?

2 个答案:

答案 0 :(得分:1)

您的线程池大小为2,而Processor个线程需要3秒才能执行。

  • 开始前两个Processors个帖子,两个都打印Started,然后在3秒后完成。
  • 然后开始接下来的两次,他们再次打印Started并在3秒后完成。
  • 然后另外两个(第5和第6个)开始,打印Started,3秒后,其中一个(或两个)完成。在这一点上,有很多事情会在大致相同的时间发生(因此订单是随机的):

    1. 主线程恢复并打印Completed
    2. 启动第7个Processor个主题并打印Started
    3. 启动第8个Processor个帖子并打印Started

因此,Completed始终会打印出6,7或8 Started张。

答案 1 :(得分:0)

所以,CountDownLatch并不能保证它会在Count Down进入{{1}后立即恢复父线程(这里我指的是你调用latch.await();的线程) }。因此,当Count Down锁定倒计时到0时会发生什么,这意味着现在父线程可以恢复其工作,这并不意味着它将获得CPU然后到那里。因此,它可以恢复,这并不意味着CPU在倒计时到0时就会安排父线程。如果还有其他线程,则有可能在父线程之前执行。 在您的情况下,它会确保它不会0 before时间打印5 ,但会Started ensure exactly 5 1}}打印StartedCompleted后。您可能还会观察到代码执行时Started正在所有<ul>打印结束时打印。