[英]java CyclicBarrier not broken with reset
I am trying to test BrokenBarrierException by resetting the cyclicbarrier in the middle of starting (awaiting) few parties (threads), please find the below sample code for the same.我正在尝试通过在启动(等待)几方(线程)的中间重置循环屏障来测试 BrokenBarrierException,请在下面找到相同的示例代码。
User class:用户类:
public class User implements Runnable {
private final String name;
private final CyclicBarrier cb;
public User(String name, CyclicBarrier cb) {
this.name = name;
this.cb = cb;
}
@Override
public void run() {
System.out.println(name+" user started !!!! ");
try {
cb.await();
} catch (InterruptedException | BrokenBarrierException e) {
System.out.println(e);
e.printStackTrace();
}
}
}
CyclicBarrierTest class: CyclicBarrierTest 类:
public class CyclicBarrierTest {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(5);
User user1 = new User("USER1", barrier);
new Thread(user1).start();
User user2 = new User("USER2", barrier);
new Thread(user2).start();
//Expected users are 5, but only 2 user threads started so far
// and resetting below which should throw barrier broken exception
barrier.reset();
if(barrier.isBroken()) {
System.out.println("Barrier broken ");
}
}
}
So, after running the main() above, I could get any exceptions and also "Barrier broken" also not printed.因此,在运行上面的 main() 之后,我可能会遇到任何异常,并且“屏障损坏”也没有打印出来。 The threads are simply waiting.
线程只是在等待。
I have referred the CyclicBarrier API below link:
我在下面的链接中提到了 CyclicBarrier API:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CyclicBarrier.html
public void reset():
公共无效重置():
Resets the barrier to its initial state.
将障碍重置为其初始状态。 If any parties are currently waiting at the barrier, they will return with a BrokenBarrierException.
如果任何一方当前正在屏障处等待,他们将返回 BrokenBarrierException。
But my above code doesn't seems to work according to the API description, so what is the problem with my above code and why it is NOT throwing BrokenBarrierException ?但是我上面的代码似乎没有根据 API 描述工作,那么我上面的代码有什么问题,为什么它没有抛出 BrokenBarrierException ?
Could you please help ?能否请你帮忙 ?
If you want exception thrown , you have to make sure barrier.reset();
如果你想抛出异常,你必须确保
barrier.reset();
executes after cb.await();
在
cb.await();
之后执行cb.await();
, but here System.out.println(name+" user started !!!! ");
, 但这里
System.out.println(name+" user started !!!! ");
is a very costly statement which makes barrier.reset();
是一个非常昂贵的语句,它使
barrier.reset();
executes too early , you can add a sleep statement before barrier.reset();
执行过早,可以在
barrier.reset();
之前添加sleep语句barrier.reset();
, say Thread.sleep(100);
,说
Thread.sleep(100);
. .
Doc of isBroken
: isBroken
文档:
true if one or more parties broke out of this barrier due to interruption or timeout since construction or the last reset, or a barrier action failed due to an exception;
如果一个或多个参与方由于自构建或上次重置以来的中断或超时而突破此障碍,或者由于异常导致障碍操作失败,则为真; false otherwise.
否则为假。
If you want it as broken , you can do something to the parties .如果你想把它弄坏,你可以给当事人做点什么。 You need remove
reset
to make threads awaiting .您需要删除
reset
以使线程等待。
public class User implements Runnable {
private final String name;
private final CyclicBarrier cb;
public User(String name, CyclicBarrier cb) {
this.name = name;
this.cb = cb;
}
@Override
public void run() {
System.out.println(name+" user started !!!! ");
try {
cb.await(1,TimeUnit.SECONDS);
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
} catch (TimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name+" user ended !!!! ");
}
}
public class CyclicBarrierTest {
public static void main(String[] args) throws Exception {
CyclicBarrier barrier = new CyclicBarrier(5);
User user1 = new User("USER1", barrier);
new Thread(user1).start();
User user2 = new User("USER2", barrier);
new Thread(user2).start();
//Expected users are 5, but only 2 user threads started so far
// and resetting below which should throw barrier broken exception
Thread.sleep(100);
// barrier.reset();
Thread.sleep(1100);
if(barrier.isBroken()) {
System.out.println("Barrier broken ");
}
}
}
Short answer:简短的回答:
On reset the barrier loses the information of previous BrokenBarrierException
(s).重置时屏障会丢失之前
BrokenBarrierException
(s) 的信息。 So any call to isBroken
after reset
will return false
.因此,任何调用
isBroken
后reset
将返回false
。
The javadoc specify this, although, not very clearly: javadoc 指定了这一点,虽然不是很清楚:
isBroken
return: true if one or more parties broke out of this barrier due to interruption or timeout since construction or the last reset , or a barrier action failed due to an exception;isBroken
return: true 如果一个或多个参与方由于自构造或上次重置以来的中断或超时而突破此屏障,或者由于异常导致屏障操作失败; false otherwise.否则为假。
Long answer:长答案:
You can see more clearly what happens if you look at source code of reset
and isBroken
:如果您查看
reset
和isBroken
源代码,您可以更清楚地看到会发生什么:
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // break the current generation
nextGeneration(); // start a new generation
} finally {
lock.unlock();
}
}
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
private void nextGeneration() {
// signal completion of last generation
trip.signalAll();
// set up next generation
count = parties;
generation = new Generation();
}
private static class Generation {
boolean broken = false;
}
public boolean isBroken() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return generation.broken;
} finally {
lock.unlock();
}
}
You can see that the reference generation.broken
holds the information about a broken barrier.您可以看到参考
generation.broken
包含有关已损坏障碍的信息。 But this is reinitialized to false
on reset.但这在重置时被重新初始化为
false
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.