我正在阅读Java Concurrency In Practice一书,并且遇到了CountDownLatch。
以下是给出的示例:
public class TestHarness {
public long timeTasks(int nThreads, final Runnable task)
throws InterruptedException {
final CountDownLatch startGate = new CountDownLatch(1);
final CountDownLatch endGate = new CountDownLatch(nThreads);
for (int i = 0; i < nThreads; i++) {
Thread t = new Thread() {
public void run() {
try {
startGate.await();
try {
task.run();
} finally {
endGate.countDown();
}
} catch (InterruptedException ignored) { }
}
};
t.start();
}
long start = System.nanoTime();
startGate.countDown();
endGate.await();
long end = System.nanoTime();
return end-start;
}
}
以下是其解释:
代码清单5.11中的TestHarness说明了锁存器的两种常见用法。 TestHarness创建了许多运行给定任务的线程 同时。它使用两个锁存器,一个“起始门”和一个“结束 闸门“。起始门的初始值为1; 结束门的初始化计数等于worker的数量 线程。每个工作线程做的第一件事是等待 起跑门;这可以确保它们都不会开始工作直到 他们都准备开始了。每个人做的最后一件事就是倒计时 在结束门上;这允许主线程有效地等待 直到最后一个工作线程完成,所以它可以 计算经过的时间。
我是Java多线程的新手,所以我无法理解给出的解释以及该程序的工作原理。
这是什么意思 -
每个工作线程做的第一件事是等待起始门; 这可以确保他们都没有开始工作,直到他们都准备好了 开始。每个人做的最后一件事是倒数结束门; 这允许主线程有效地等待直到最后一个 工作线程已完成,因此可以计算经过的时间。
以及这段代码如何正常工作:
Thread t = new Thread() {
public void run() {
try {
startGate.await();
try {
task.run();
} finally {
endGate.countDown();
}
} catch (InterruptedException ignored) { }
}
};
和
long start = System.nanoTime();
startGate.countDown();
endGate.await();
long end = System.nanoTime();
return end-start;
请帮助我理解这个概念。
答案 0 :(得分:4)
这段代码
Thread t = new Thread() {
public void run() {
try {
startGate.await();
try {
task.run();
} finally {
endGate.countDown();
}
} catch (InterruptedException ignored) { }
}
};
设置所需的所有线程。每个线程将等待startGate
被“打开”,即。它的计数为0.当线程完成执行Runnable
时,即。 run()
返回,他们将倒计时endGate
。这就是这个
每个工作线程做的第一件事是等待起始门; 这可以确保他们都没有开始工作,直到他们都准备好了 开始。每个人做的最后一件事就是在结束门上倒数;
的装置。
设置完所有线程后,执行此代码。
long start = System.nanoTime();
startGate.countDown();
endGate.await();
long end = System.nanoTime();
return end-start;
当前线程倒计时startGate
,允许所有其他线程开始执行其Runnable
,即。 task.run()
。然后等待endGate
上的(块)倒计数到0.此时,它计算所花费的时间并返回该值。这就是这个
这允许主线程有效地等待直到最后一个 工作线程已完成,因此可以计算经过的时间。
装置
答案 1 :(得分:2)
确实不是很清楚 你的实际问题是什么,或者只要不清楚你已经知道什么就应该解释代码。
但是,这里使用的概念并不复杂,通过删除错误处理并使用内联注释指出重要部分,它可能已经变得更加清晰:
for (int i = 0; i < nThreads; i++) {
// This will create and start a new thread
// that executes the code in the "run" method
Thread t = new Thread() {
public void run() {
// Wait until this thread gets the start signal
startGate.await();
// Perform some arbitrary work
task.run();
// Notify everybody that this thread has finished his work
endGate.countDown();
}
};
t.start();
}
// Give all threads the start signal: Counting down
// where will cause the latch to reach the value 0,
// and every thread that is waiting at "startGate.await()"
// will proceed his work
startGate.countDown();
// Wait here until all threads have called "endGate.countDown()".
endGate.await();
答案 2 :(得分:1)
startGate
最初设置为1,因此所有线程都会等到计数结束。
endGate
被初始化为我们计划使用的线程数,所以它会等到所有线程都通过结束门之后再报告所花费的时间。
// Take a note of the time.
long start = System.nanoTime();
// Start all of the threads running - they all wait for this signal by calling startGate.await().
startGate.countDown();
// Wait for all threads to complete - they record their finish with endGate.countDown().
endGate.await();
// Note the time.
long end = System.nanoTime();
答案 3 :(得分:0)
package com.sample.thread;
import java.util.concurrent.CountDownLatch;
public class CDLExample {
private static CountDownLatch latch;
public static void main(String args[]) {
latch = new CountDownLatch(2);
new Thread("main") {
public void run() {
try {
latch.await();
System.out
.println("\nStarting Main thread as all other thread is started");
System.out.println("CountDownLatch demonstrated: "
+ Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
new Thread("first") {
public void run() {
System.out.println("Print Odd Number: "
+ Thread.currentThread().getName());
try {
for (int i = 1; i < 20; i = i + 2) {
System.out.print(i + " ");
Thread.sleep(50);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
}
}.start();
new Thread("second") {
public void run() {
try {
Thread.sleep(1000);
System.out.println("\nPrint Even Number: "
+ Thread.currentThread().getName());
for (int i = 2; i < 20; i = i + 2) {
Thread.sleep(50);
System.out.print(i + " ");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
}
}.start();
}
}