为什么 java 中的 Countdownlatch 不能在给定的锁存器计数时停止?
why can't Countdownlatch in java stops at given latch count?
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 次后打印 "Started" 因为锁存器倒数到 5 - 0,为什么它总是第 7 次或第 8 次?我理解错了吗?
因此,CountDownLatch
不保证一旦倒计时进入 0
。因此,当 Count Down 锁存器倒计时到 0 时会发生什么,这意味着现在父线程可以恢复其工作,但这并不意味着它会在那里获得 CPU。所以,它可以恢复并不意味着CPU调度父线程倒计时到0
。如果还有其他线程,那么它们是否有可能在父线程之前执行。 在你的情况下,它确保它不会执行 before
5
时间打印 Started
但它确实 ensure
它会打印 5
次 Started
后为 exactly
。您可能还会在代码的某个执行过程中观察到 Completed
在所有 Started
打印结束时打印。
您的线程池大小为 2,您的 Processor
线程执行需要 3 秒。
- 前两个
Processors
线程启动,都打印 Started
并在 3 秒后完成。
- 然后接下来的两个开始,它们再次打印
Started
并在 3 秒后完成。
然后开始另外两个(第 5 个和第 6 个),打印 Started
并在 3 秒后其中一个(或两个)完成。在这一点上,有几件事情将大致同时发生(所以顺序是随机的):
- 主线程恢复并打印
Completed
- 第 7 个
Processor
线程启动并打印 Started
- 第 8 个
Processor
线程启动并打印 Started
因此,Completed
前面总是有 6、7 或 8 个 Started
打印输出。
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 次后打印 "Started" 因为锁存器倒数到 5 - 0,为什么它总是第 7 次或第 8 次?我理解错了吗?
因此,CountDownLatch
不保证一旦倒计时进入 0
。因此,当 Count Down 锁存器倒计时到 0 时会发生什么,这意味着现在父线程可以恢复其工作,但这并不意味着它会在那里获得 CPU。所以,它可以恢复并不意味着CPU调度父线程倒计时到0
。如果还有其他线程,那么它们是否有可能在父线程之前执行。 在你的情况下,它确保它不会执行 before
5
时间打印 Started
但它确实 ensure
它会打印 5
次 Started
后为 exactly
。您可能还会在代码的某个执行过程中观察到 Completed
在所有 Started
打印结束时打印。
您的线程池大小为 2,您的 Processor
线程执行需要 3 秒。
- 前两个
Processors
线程启动,都打印Started
并在 3 秒后完成。 - 然后接下来的两个开始,它们再次打印
Started
并在 3 秒后完成。 然后开始另外两个(第 5 个和第 6 个),打印
Started
并在 3 秒后其中一个(或两个)完成。在这一点上,有几件事情将大致同时发生(所以顺序是随机的):- 主线程恢复并打印
Completed
- 第 7 个
Processor
线程启动并打印Started
- 第 8 个
Processor
线程启动并打印Started
- 主线程恢复并打印
因此,Completed
前面总是有 6、7 或 8 个 Started
打印输出。