有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

为什么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.");
    }

}

输出:

开始 起动 起动 起动 起动 起动 起动 完成` 起动 起动 开始

在上面的代码中,“已完成”应该在6次“开始”后打印,因为闩锁倒计时为5-0,为什么总是第7次或第8次?我理解错了吗


共 (2) 个答案

  1. # 1 楼答案

    你的线程池大小为2,你的Processor线程需要3秒钟才能执行

    • 前两个Processors线程启动,两个线程都打印Started,并在3秒钟后完成
    • 然后,接下来的两个都开始打印Started,并在3秒钟后完成
    • 然后另外两个(第五和第六个)开始打印Started,三秒钟后其中一个(或两个)完成。在这一点上,几乎同时会发生多件事情(因此顺序是随机的):

      1. 主线程继续并打印Completed
      2. 第七个Processor线程启动并打印Started
      3. 第八个Processor线程启动并打印Started

    因此,Completed前面总是有6、7或8Started个打印输出

  2. # 2 楼答案

    因此,CountDownLatch并不保证它会在倒计时一到0就恢复父线程(这里我指的是调用latch.await();的线程)的执行。所以,当倒计时闩锁倒计时为0时会发生什么,这意味着现在父线程可以继续工作,但这并不意味着它将获得CPU。因此,它可以恢复,这并不意味着CPU会在倒计时到0时立即安排父线程。如果还有其他线程,那么这些线程可能会在父线程之前执行在您的情况下,它确保不会执行before时间打印5,但它确实会ensure在打印5Started后执行exactly。您还可以在代码的某个特定执行时观察到Completed在所有Started打印结束时正在打印