java - 异步等待条件
问题描述
我想异步等待一个条件。下面是一个使用awaitility
库的示例,但据我所知,awaitility
它是阻塞的(即不是异步的)。关于如何以本机方式(或可能使用另一个库)以异步方式实现此目的的任何想法。任何想法表示赞赏。
await().forever().with().pollInterval(1, TimeUnit.SECONDS)
.until(() -> redis.eval(lockscript, ScriptOutputType.BOOLEAN, "mutex:" + key).equals(true));
await().atMost(timeout, TimeUnit.SECONDS).with().pollInterval(1, TimeUnit.SECONDS).until(
() -> redis.eval(lockscript, ScriptOutputType.BOOLEAN, "mutex:" + key).equals(true));
解决方案
正如评论中提到的,您可以使用Completable Futures和Scheduled Executor来获得您想要的东西(或者至少是接近的东西)。
我们可以until
像这样定义一个方法:
public void until(Callable<Boolean> method, long timeout, TimeUnit unit, ScheduledExecutorService s) throws Exception {
s.scheduleAtFixedRate(() -> {
try {
Boolean returnVal = method.call();
if (returnVal == true)
s.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}, timeout, timeout, unit);
}
这样做是接受一个传递scheduledExecutor
并调用任何Callable
方法(在这种情况下使用返回值Boolean
,因为这是您想要的。这将循环每次timeout
直到满足要求并且调度程序关闭。
注意:如果你想重用调度器,不要调用shutdown()
它,而是cancel()
.
我们这样称呼它的方式如下:
ScheduledExecutorService sched = new ScheduledThreadPoolExecutor(1);
until(() -> basicBoolStatement(), 1, TimeUnit.SECONDS, sched);
我们不需要调度器拥有多个线程。只需传入任何其他返回布尔值的东西basicBoolStatement()
。
如果你想给你的请求一个时间限制,那么你可以做额外的电话,像这样:
public static void untilAtMost(Callable<Boolean> method, long untilTimeout, long atMostTimeout, TimeUnit unit, ScheduledExecutorService s) throws Exception {
CompletableFuture.runAsync(() -> {
try {
until(method, untilTimeout, unit, s);
} catch (Exception e) {
e.printStackTrace();
}
});
ScheduledExecutorService sched = new ScheduledThreadPoolExecutor(1);
sched.schedule(() -> {
s.shutdown();
sched.shutdown();
}, atMostTimeout, unit);
}
在这里,我们重用了until
上面的方法,但是我们有另一个调度器,它会shutdown()
在时间过去until
时执行调度器atMostTimeout
。
同样,调用代码看起来像:
ScheduledExecutorService sched = new ScheduledThreadPoolExecutor(1);
untilAtMost(() -> basicBoolStatement(), 10, 1, TimeUnit.SECONDS, sched);
编辑:如果您不想像处理Callable
界面那样处理异常,您可以使用Supplier
.
免责声明:对于混乱的代码感到抱歉,但这只是一个概念证明。