1. 背景
之前介绍了一篇awaitility快速入门的文章:异步校验工具awaitility快速入门,该工具很好地解决了校验异步操作的问题,其中封装了很多便捷的用法,重点是在规定时间内,轮询结果;本文以源码的方式,介绍一下工具内部是怎么实现的,理解开发的设计思路,对以后解决工作中的问题是有帮助的。
2. 核心源码梳理
2-1. 例子
// 异步任务,每隔1s, count累加1
class CounterServiceImpl implements CounterService {
private volatile int count = 0;
public void run() {
new Thread(new Runnable() {
@Override
public void run() {
try {
for (int index = 0; index < 5; index++) {
Thread.sleep(1000);
count += 1;
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}).start();
}
public int getCount() {
return count;
}
}
@Test
public void testAsynchronousPoll() {
final CounterService service = new CounterServiceImpl();
service.run();
// 轮询查询,pollInterval每隔多少时间段轮询,pollDelay延迟校验时间
with().atMost(60, SECONDS).and().pollInterval(ONE_HUNDRED_MILLISECONDS).and().pollDelay(50, MILLISECONDS).await("count is greater 6").until(
new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return service.getCount() == 6;
}
});
}
2-2. 核心源码分析
例子中:
// 设置超时时间,6s
atMost(6, SECONDS)
// 设置间隔100ms
pollInterval(ONE_HUNDRED_MILLISECONDS)
// 设置延迟50ms
pollDelay(50, MILLISECONDS)
// 设置提示语
await("count is greater 6")
// 连接
and()
// 等待java.util.concurrent.Callable返回true
until(
new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return service.getCount() == 6;
}
});
ConditionFactory类所在包路径:
package org.awaitility.core
ConditionFactory类是一个Condition工厂,with()会新建一个ConditionFactory实例:
public static ConditionFactory with() {
return new ConditionFactory(defaultWaitConstraint, defaultPollInterval, defaultPollDelay,
defaultCatchUncaughtExceptions, defaultExceptionIgnorer, defaultConditionEvaluationListener);
}
ConditionFactory带参构造函数如下:
/**
* Instantiates a new condition factory.
*
* @param timeoutConstraint the timeout
* @param pollInterval the poll interval
* @param pollDelay The delay before the polling starts
* @param exceptionsIgnorer the ignore exceptions
* @param catchUncaughtExceptions the catch uncaught exceptions
*/
public ConditionFactory(WaitConstraint timeoutConstraint, PollInterval pollInterval, Duration pollDelay,
boolean catchUncaughtExceptions, ExceptionIgnorer exceptionsIgnorer,
ConditionEvaluationListener conditionEvaluationListener) {
this(null, timeoutConstraint, pollInterval, pollDelay, catchUncaughtExceptions, exceptionsIgnorer,
conditionEvaluationListener);
}
构造函数的参数值:
/**
* The default poll interval (fixed 100 ms).
*/
private static volatile PollInterval defaultPollInterval = DEFAULT_POLL_INTERVAL;
/**
* The default wait constraint (10 seconds).
*/
private static volatile WaitConstraint defaultWaitConstraint = AtMostWaitConstraint.TEN_SECONDS;
/**
* The default poll delay
*/
private static volatile Duration defaultPollDelay = DEFAULT_POLL_DELAY;