话费便宜。显示代码。
MyCyclicBarrier.java
public class MyCyclicBarrier extends Thread{
private CyclicBarrier cyclicBarrier;
public MyCyclicBarrier(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
System.out.println("Thread start." + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(2); //biz code
System.out.println("Thread "+Thread.currentThread().getName()+" is waiting for the other Threads."+
"\n\t\t\t\tIt's parties is "+cyclicBarrier.getParties()+
"\n\t\t\t\tWaiting for "+cyclicBarrier.getNumberWaiting()+" Threads");
cyclicBarrier.await(3,TimeUnit.SECONDS);
} catch (InterruptedException | BrokenBarrierException | TimeoutException e) {
e.printStackTrace();
}
System.out.println("Thread end."+Thread.currentThread().getName());
}
}
TestCyclicbarrier.java
public class TestCyclicbarrier1 {
public static void main(String[] args) {
int length = 5;
long start = System.currentTimeMillis();
CyclicBarrier cyclicBarrierWithRunnable = new CyclicBarrier(length, () -> {
System.out.println("the final reach Thread is " + Thread.currentThread().getName());
long end = System.currentTimeMillis();
System.out.println("cost totally :" + (end - start) / 1000 + "s");
});
for (int i = 0; i < length; i++) {
if (i != 4) {
new MyCyclicBarrier(cyclicBarrierWithRunnable).start();
} else {
try {
TimeUnit.SECONDS.sleep(2);
new MyCyclicBarrier(cyclicBarrierWithRunnable).start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
输出:
Thread start.Thread-1
Thread start.Thread-0
Thread start.Thread-2
Thread start.Thread-3
Thread Thread-0 is waiting for the other Threads.
It's parties is 5
Waiting for 0 Threads
Thread Thread-3 is waiting for the other Threads.
It's parties is 5
Waiting for 0 Threads
Thread start.Thread-4
Thread Thread-1 is waiting for the other Threads.
It's parties is 5
Waiting for 0 Threads
Thread Thread-2 is waiting for the other Threads.
It's parties is 5
Waiting for 1 Threads
Thread Thread-4 is waiting for the other Threads.
It's parties is 5
Waiting for 4 Threads
the final reach Thread is Thread-4
cost totally :4s
Thread end.Thread-4
Thread end.Thread-0
Thread end.Thread-3
Thread end.Thread-2
Thread end.Thread-1
我在网上找了很久。但没有类似的答案。请帮助或尝试提供一些想法!我刚刚开始学习CyclicBarrier
。
我想知道我是否误解了 CyclicBarrier.await(int timeout,TimeUnit unit)
。线程 0 到 3 已经达到了花费 2 秒的屏障点。同时,最后一个线程在等待 2 秒后启动。1 秒后,0 到 3 线程达到指定的超时时间,其中 4 线程仍然执行自己的代码。这里的问题是:为什么 CyclicBarrier.await(int timeout, TimeUnit unit)
没有在这里抛出 TimeOutException
?
答案 0 :(得分:0)
线程 0 到 3 已经达到了花费 2 秒的屏障点。
这是正确的。
<块引用>同时等待 2 秒后最终线程启动。
正确。请注意,到该线程启动时,其他 4 个线程正在等待 CB(3 秒超时,即我们有 3 秒直到 TimeoutException
发生)。
但是线程 4 在 run
方法中只休眠了 2 秒(我们离 TimeoutException
还只有 1 秒)。
当谈到 await
时,它是最后一个线程 - 所以它不必再等待了。因此,屏障动作得到运行,其他动作被解除阻塞——来自 javadoc,
如果当前线程是最后一个到达的线程,并且 在构造函数中提供了非空屏障操作,然后当前线程在允许其他线程继续之前运行该操作。
如果您在启动线程 4 之前睡眠四秒钟,您会得到一个 TimeoutException
。
try {
TimeUnit.SECONDS.sleep(4);
new MyCyclicBarrier(cyclicBarrierWithRunnable).start();
} catch (InterruptedException e) {
e.printStackTrace();
}
答案 1 :(得分:0)
你似乎认为线程启动时超时就开始了:
<块引用>线程 0 到 3 已经达到了花费 2 秒的屏障点。
<块引用>1 秒后 0 到 3 个线程达到指定的超时时间
这是错误的。当你打电话
cyclicBarrier.await(3,TimeUnit.SECONDS);
线程到达该点所用的时间无关紧要 - 从调用方法 cyclicBarrier.await()
的那一刻起超时是 3 秒。
由于线程 4 只有 2 秒的额外延迟,因此它仍然及时到达。
为了进一步澄清这是时间线的样子:
t=0s
main()
创建 CyclicBarrier
并启动线程 0 到 3TimeUnit.SECONDS.sleep(2);
TimeUnit.SECONDS.sleep(2);
t=2s
main()
开始线程 4cyclicBarrier.await(3,TimeUnit.SECONDS);
,这意味着它们将在 t=5s (t=2s + 3s) 处被中断TimeUnit.SECONDS.sleep(2);
t=4s
cyclicBarrier.await(3,TimeUnit.SECONDS);
。cyclicBarrier.await(3,TimeUnit.SECONDS);
内,CyclicBarrier
的条件已满足,所有线程继续CyclicBarrier
的线程)