所以…
我有一个实用程序类,它在初始调用在给定时间后没有返回之后执行重试(理论上是对任何对象),并持续执行重试,直到任何源返回数据或直到所有资源都用完为止。这种用途
ExecutorCompletionService
的
.poll
方法触发何时重试。请参阅下面的实用程序类代码…
final RetrySources[] retrySources = getRetrySources(originalSource);
Future resultFuture = null;
final List> futures = new ArrayList<>(retrySources.length);
for (int tryIndex = 0; tryIndex < retrySources.length && resultFuture == null; tryIndex++) {
final int tryIndexCopy = tryIndex;
futures.add(ecs.submit(() -> client.call(retrySources[tryIndexCopy], tryIndexCopy)));
resultFuture = ecs.poll(millisBeforeRetry, TimeUnit.MILLISECONDS);
}
if (resultFuture == null) {
resultFuture = ecs.take();
}
return resultFuture.get();
…我的问题是我重新编写测试不是为了使用睡眠,而是为了使用
CountDownLatch
. 看下面我的一个测试…
@Test
public void call_firstRetryFinishesAfterLimitButBeforeSecondRetryDoes_triggersSecondRetryButUsesFirstResult() throws Exception {
final String readResult1 = "a";
final String readResult2 = "b";
final CountDownLatch signal1 = new CountDownLatch(1);
final CountDownLatch signal2 = new CountDownLatch(1);
expect(mockReadOperation.call(readOptions[0], 0)).andStubAnswer(() -> {
signal1.await(); // This causes the test to spin forever
// Thread.sleep(1000); // Swapping the line above for this, makes it work
return readResult1;
});
expect(mockReadOperation.call(readOptions[1], 1)).andStubAnswer(() -> {
signal1.countDown();
signal2.await(); // For this test case, make the second retry never return
return readResult2;
});
replay(mockReadOperation);
final ReadOption readOption = ReadOption.primary();
final String result = subject.call(readOption);
assertThat(result).isEqualTo("a");
}
…注意我的
执行完成服务
定义为…
private final ExecutorCompletionService executorCompletionService = new ExecutorCompletionService(Executors.newFixedThreadPool(2));
…因为我的测试是在主线程中运行的,而每个调用都是作为
执行完成服务
泳池,我不明白为什么
signal1.await();
使测试永远旋转并记录注释,即切换该行以进入睡眠状态会导致测试通过。
任何帮助都非常感谢。