gpt4 book ai didi

java - 多次调用 CountDownLatch.await(int) 超时

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:06:03 30 4
gpt4 key购买 nike

我使用 CountDownLatch 等待来自另一个组件(在不同线程中运行)的特定事件。以下方法符合我的软件的语义,但我不确定它是否按我预期的那样工作:

mCountDownLatch.await(3000, TimeUnit.MILLISECONDS)
otherComponent.aStaticVolatileVariable = true;
mCountDownLatch.await(3500, TimeUnit.MILLISECONDS);
... <proceed with other stuff>

场景应该是这样的:我等了 3 秒,如果 latch 没有倒数到 0,我就用那个变量通知其他组件,然后我最多等 3.5 秒。如果再次超时,那我就不管了,继续进行其他操作。

注意:我知道它看起来不像那样,但上面的场景在我的软件中是完全合理和有效的。

我确实阅读了 await(int,TimeUnit) 和 CountDownLatch 的文档,但我不是 Java/Android 专家,所以我需要确认。对我来说,所有场景看起来都有效:

  • 如果第一个await成功,那么另一个await会立即返回
  • 如果第一个await超时,那么另一个await仍然有效;因此,如果另一个线程注意到静态信号,第二个await 可能成功返回
  • 两个等待调用都超时(根据我的软件语义,这很好)

我是否正确使用 await(...)?即使同一对象上的前一个 await(...) 超时,是否可以按上述方式使用第二个 await(...)?

最佳答案

如果我正确理解你的问题,这个测试证明你所有的假设/要求都是真实的/满足的。 (使用 JUnit 和 Hamcrest 运行。)请注意 runCodeUnderTest() 方法中的代码,尽管它穿插着时间记录并且超时减少了 10 倍。

import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.assertThat;

public class CountdownLatchTest {
static volatile boolean signal;
CountDownLatch latch = new CountDownLatch(1);
long elapsedTime;
long[] wakeupTimes = new long[2];

@Before
public void setUp() throws Exception {
signal = false;
}

@Test
public void successfulCountDownDuringFirstAwait() throws Exception {
countDownAfter(150);
runCodeUnderTest();
assertThat((double) elapsedTime, closeTo(150, 10));
assertThat(wakeupTimeSeparation(), lessThan(10));
}

@Test
public void successfulCountDownDuringSecondAwait() throws Exception {
countDownAfter(450);
runCodeUnderTest();
assertThat((double) elapsedTime, closeTo(450, 10));
assertThat((double) wakeupTimeSeparation(), closeTo(150, 10));
}

@Test
public void neverCountDown() throws Exception {
runCodeUnderTest();
assertThat((double) elapsedTime, closeTo(650, 10));
assertThat((double) wakeupTimeSeparation(), closeTo(350, 10));
}

@Test
public void countDownAfterSecondTimeout() throws Exception {
countDownAfter(1000);
runCodeUnderTest();
assertThat((double) elapsedTime, closeTo(650, 10));
assertThat((double) wakeupTimeSeparation(), closeTo(350, 10));
}

@Test
public void successfulCountDownFromSignalField() throws Exception {
countDownAfterSignal();
runCodeUnderTest();
assertThat((double) elapsedTime, closeTo(300, 10));
}

private int wakeupTimeSeparation() {
return (int) (wakeupTimes[1] - wakeupTimes[0]);
}

private void runCodeUnderTest() throws InterruptedException {
long start = System.currentTimeMillis();
latch.await(300, TimeUnit.MILLISECONDS);
wakeupTimes[0] = System.currentTimeMillis();
signal = true;
latch.await(350, TimeUnit.MILLISECONDS);
wakeupTimes[1] = System.currentTimeMillis();
elapsedTime = wakeupTimes[1] - start;
}

private void countDownAfter(final long millis) throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
sleep(millis);
latch.countDown();
}
}).start();
}

private void countDownAfterSignal() {
new Thread(new Runnable() {
@Override
public void run() {
boolean trying = true;
while (trying) {
if (signal) {
latch.countDown();
trying = false;
}
sleep(5);
}
}
}).start();
}

private void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new IllegalStateException("Unexpected interrupt", e);
}
}
}

关于java - 多次调用 CountDownLatch.await(int) 超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10770419/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com