java - 如何优雅地在java中合并具有相同参数的方法调用
问题描述
背景:
- 我有一个
queryDB
带参数的 java 方法p
,并且queryDB
是资源消耗。 - 对于每个参数
p
,结果queryDB
可能会随时间而变化。
我想要达到的目标:
如果有人queryDB
用参数调用,p=x
而另一个线程已经queryDB
用相同的参数调用p=x
并等待结果,则该线程实际上不会执行queryDB
,而是等待另一个线程的结果。
注意:我知道如何在 vanilla java 中实现这一点,但我想要一个单行解决方案。
香草java:
public class InvocationMerger<K, R> {
private Map<K, CompletableFuture<R>> futureMap = new ConcurrentHashMap<>();
public R invoke(K key, Function<K, R> func) throws ExecutionException, InterruptedException {
AtomicReference<CompletableFuture<R>> createdFutureRef = new AtomicReference<>();
CompletableFuture<R> pendingFuture = futureMap.computeIfAbsent(key, k -> {
createdFutureRef.set(new CompletableFuture<>());
return createdFutureRef.get();
});
if (createdFutureRef.get() != null) {
CompletableFuture<R> createdFuture = createdFutureRef.get();
try {
R result = func.apply(key);
futureMap.remove(key, createdFuture);
createdFuture.complete(result);
return result;
} catch (Throwable e) {
futureMap.remove(key, createdFuture);
createdFuture.completeExceptionally(e);
throw e;
}
} else {
return pendingFuture.get();
}
}
}
解决方案
推荐阅读
- linux - Collectd 无法读取 Ansible 发送的配置文件
- c# - 带有 OR 条件的 if 语句逻辑
- javascript - 有没有办法用变量替换 HTML 标签中的值并要求值来构造 html?
- sip - InitialFilterCriteria 中“SessionCase”标签的可能值是什么?
- php - Laravel - 如何通过 laravel api 访问关系
- reactjs - DropDown 不填充来自 API 调用的数据
- mysql - sql中有没有办法从数据中获取月份名称
- angularjs - 使用 AJAX (AngularJS) 重置 Laravel 密码
- php - Doctrine\DBAL\Exception\UniqueConstraintViolationException 尝试在教义 2 上使用表继承插入
- xml - 需要在 xml 文件中编辑节点的属性值