在运行每个线程时,为什么countdown.getCount()总是打印'3',即使前一个线程已经调用了countdown.countDown()并将Latch Count减少了1?
我很遗憾Java知道Latch Count已达到0,因此它可以释放所有3个线程。
import java.util.concurrent.CountDownLatch;
class b {
static final CountDownLatch countdown = new CountDownLatch(3);
public static void main(String[] args) {
for (int i = 0; i < 3; ++i) {
Thread t = new Thread() {
public void run() {
System.out.printf("Starting on %d other threads.\n",
countdown.getCount());
countdown.countDown();
System.out.printf("new on %d other threads.\n",
countdown.getCount());
try {
countdown.await(); // waits until everyone reaches this
// point
// System.out.println("Go again : "
// +countdown.getCount());
} catch (Exception e) {
}
}
};
t.start();
}
System.out.println("Go");
}
}
答案 0 :(得分:2)
你并行启动3个线程。根据它们开始的速度,它们都可以在任何线程设法调用countDown()
之前打印“3”(至少对于“开始......”行)。但是,“new on ...”行应打印出2到0之间的某些数字范围。
答案 1 :(得分:0)
绝对有可能所有三个线程打印&#34;从3开始...&#34;当线程并行运行时,计数不会改变,直到线程执行countDown()。为了真正理解发生了什么,我建议您在print语句之前添加System.nanoTime()和线程名称,如下所示:
...
Thread t = new Thread("Thread-" + i) {
...
System.out.printf("%d> %s: Starting on %d other threads.\n", System.nanoTime(), getName(), countdown.getCount());
countdown.countDown();
System.out.printf("%d> %s: new on %d other threads.\n", System.nanoTime(), getName(), countdown.getCount());
有时您会得到如下所示的输出,这可能会让您觉得Thread-2无视Thread-1对countDown的调用:
1407489646569321000> Thread-0: Starting on 3 other threads.
1407489646569324000> Thread-1: Starting on 3 other threads.
1407489646602463000> Thread-1: new on 1 other threads.
1407489646569513000> Thread-2: Starting on 3 other threads.
1407489646602107000> Thread-0: new on 2 other threads.
1407489646603275000> Thread-2: new on 0 other threads.
然而,事实并非如此,我们可以通过查看时间戳来验证正确的操作顺序。输出中的混淆是由于线程调度中固有的不可预测性,这取决于哪个线程获得cpu splice。
话虽如此,根据线程安排或延迟,它们可能并不总是打印3。例如,尝试按如下所示放置Thread.sleep(..):
public static void main(String[] args) throws Exception {
for (int i = 0; i < 3; ++i) {
Thread t = new Thread() {
public void run() {
/* As before */
}
};
t.start();
Thread.sleep(100); // Artificial Delay
}
}
现在你应该看到不同的结果,如下所示:!
1407490223575404000> Thread-0: Starting on 3 other threads.
1407490223607879000> Thread-0: new on 2 other threads.
1407490223676233000> Thread-1: Starting on 2 other threads.
1407490223676818000> Thread-1: new on 1 other threads.
1407490223777623000> Thread-2: Starting on 1 other threads.
1407490223778221000> Thread-2: new on 0 other threads.
在内部,CountDownLatch维护一个先进先出等待队列(参见.GrathQueuedSynchronizer)。计数值是同步的,等待线程仅在计数变为0或其他线程中断等待线程时释放。这是锁存器用于跟踪所有线程何时到达锁存器的机制。
如果您有兴趣了解测试环境中的闩锁,请结帐http://razshahriar.com/2014/08/testing-asynchronous-code-in-java-with-countdownlatch/ 希望这有助于澄清您对计划行为的调查。