CountdownLatch await() 没有等待最后一个线程结束
CountdownLatch await() is not waiting for last thread to end
我写了一小段程序来演示 java 中 CountDownLatch class 的用法。
但是,它没有按预期工作。我创建了 5 个线程并为每个线程分配了任务。现在,每个线程都将等待启动信号。一旦开始信号打开,所有线程开始工作并调用 countDown()。现在,我的主线程等待所有线程完成其工作,直到它收到完成信号。但是输出不是预期的。如果我在概念中遗漏任何内容,请提供帮助。
下面是程序。
class Task implements Runnable{
private CountDownLatch startSignal;
private CountDownLatch doneSignal;
private int id;
Task(int id, CountDownLatch startSignal, CountDownLatch doneSignal){
this.startSignal = startSignal;
this.doneSignal = doneSignal;
this.id = id;
}
@Override
public void run() {
try {
startSignal.await();
performTask();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void performTask() {
try {
System.out.println("Task started by thread : " + id);
Thread.sleep(5000);
doneSignal.countDown();
System.out.println("Task ended by thread : " + id);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class CountDownLatchExample {
public static void main(String[] args) {
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(5);
for(int i=0; i < 5; ++i) {
new Thread(new Task(i, startSignal, doneSignal)).start();
}
System.out.println("Press enter to start work");
new Scanner(System.in).nextLine();
startSignal.countDown();
try {
doneSignal.await();
System.out.println("All Tasks Completed");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出
Press enter to start work
Task started by thread : 0
Task started by thread : 4
Task started by thread : 3
Task started by thread : 2
Task started by thread : 1
Task ended by thread : 4
Task ended by thread : 2
Task ended by thread : 1
All Tasks Completed
Task ended by thread : 0
Task ended by thread : 3
预期输出
Press enter to start work
Task started by thread : 0
Task started by thread : 4
Task started by thread : 3
Task started by thread : 2
Task started by thread : 1
Task ended by thread : 4
Task ended by thread : 2
Task ended by thread : 1
Task ended by thread : 0
Task ended by thread : 3
All Tasks Completed
在您的 Task
class 中,您有:
doneSignal.countDown();
System.out.println("Task ended by thread : " + id);
换句话说,在打印“任务结束”之前,您对闩锁倒数。这允许主线程从对 doneSignal.await()
的调用中唤醒并在所有“任务结束之前打印“所有任务已完成” " 打印语句完成。尽管请注意“错误输出”并不总是会发生;有时您会得到预期的输出。
只需切换这两行代码即可保证您想要的输出:
System.out.println("Task ended by thread : " + id);
doneSignal.countDown();
这确保打印语句 happens-before doneSignal.countDown()
调用本身 happens-before来自 doneSignal.await()
的主线程 returns。因此,现在上面的“task ended”打印语句happens-before主线程被唤醒并打印“所有任务已完成”消息。
我写了一小段程序来演示 java 中 CountDownLatch class 的用法。 但是,它没有按预期工作。我创建了 5 个线程并为每个线程分配了任务。现在,每个线程都将等待启动信号。一旦开始信号打开,所有线程开始工作并调用 countDown()。现在,我的主线程等待所有线程完成其工作,直到它收到完成信号。但是输出不是预期的。如果我在概念中遗漏任何内容,请提供帮助。 下面是程序。
class Task implements Runnable{
private CountDownLatch startSignal;
private CountDownLatch doneSignal;
private int id;
Task(int id, CountDownLatch startSignal, CountDownLatch doneSignal){
this.startSignal = startSignal;
this.doneSignal = doneSignal;
this.id = id;
}
@Override
public void run() {
try {
startSignal.await();
performTask();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void performTask() {
try {
System.out.println("Task started by thread : " + id);
Thread.sleep(5000);
doneSignal.countDown();
System.out.println("Task ended by thread : " + id);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class CountDownLatchExample {
public static void main(String[] args) {
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(5);
for(int i=0; i < 5; ++i) {
new Thread(new Task(i, startSignal, doneSignal)).start();
}
System.out.println("Press enter to start work");
new Scanner(System.in).nextLine();
startSignal.countDown();
try {
doneSignal.await();
System.out.println("All Tasks Completed");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出
Press enter to start work
Task started by thread : 0
Task started by thread : 4
Task started by thread : 3
Task started by thread : 2
Task started by thread : 1
Task ended by thread : 4
Task ended by thread : 2
Task ended by thread : 1
All Tasks Completed
Task ended by thread : 0
Task ended by thread : 3
预期输出
Press enter to start work
Task started by thread : 0
Task started by thread : 4
Task started by thread : 3
Task started by thread : 2
Task started by thread : 1
Task ended by thread : 4
Task ended by thread : 2
Task ended by thread : 1
Task ended by thread : 0
Task ended by thread : 3
All Tasks Completed
在您的 Task
class 中,您有:
doneSignal.countDown(); System.out.println("Task ended by thread : " + id);
换句话说,在打印“任务结束”之前,您对闩锁倒数。这允许主线程从对 doneSignal.await()
的调用中唤醒并在所有“任务结束之前打印“所有任务已完成” " 打印语句完成。尽管请注意“错误输出”并不总是会发生;有时您会得到预期的输出。
只需切换这两行代码即可保证您想要的输出:
System.out.println("Task ended by thread : " + id);
doneSignal.countDown();
这确保打印语句 happens-before doneSignal.countDown()
调用本身 happens-before来自 doneSignal.await()
的主线程 returns。因此,现在上面的“task ended”打印语句happens-before主线程被唤醒并打印“所有任务已完成”消息。