Java 使异步查询同步
我有一个底层异步无序查询/响应系统,我想使其同步。查询和响应可以通过使用唯一ID标记查询来映射,而唯一ID又将伴随相应的响应 我的同步尝试使用了两个s:一个从ID映射到结果,另一个从相同ID映射到es。执行查询时,代码如下所示:Java 使异步查询同步,java,multithreading,concurrency,Java,Multithreading,Concurrency,我有一个底层异步无序查询/响应系统,我想使其同步。查询和响应可以通过使用唯一ID标记查询来映射,而唯一ID又将伴随相应的响应 我的同步尝试使用了两个s:一个从ID映射到结果,另一个从相同ID映射到es。执行查询时,代码如下所示: public Result execute(Query query) throws InterruptedException { int id = atomicInteger.incrementAndGet(); CountDownLatch latch
public Result execute(Query query) throws InterruptedException {
int id = atomicInteger.incrementAndGet();
CountDownLatch latch = new CountDownLatch(1);
latchMap.put(id, latch);
query.executeAsyncWithId(id); // Probably returns before result is ready
try {
latch.await(); // Blocks until result is ready
return resultMap.remove(id);
} catch (InterruptedException e) {
latchMap.remove(id); // We are not waiting anymore
throw e;
}
}
以及处理传入结果的代码:
public void handleResult(Result result) {
int id = result.getId();
CountDownLatch latch = latchMap.remove(id);
if (latch == null) {
return; // Nobody wants result
}
resultMap.put(id, result);
latch.countDown();
}
该方法是从一个线程调用的,该线程读取来自底层系统的所有传入结果(只有一个这样的读取器线程)
首先,我不确定线程的安全性,但似乎也没有必要为此使用两个
HashMap
s(特别是因为从未重用id)。有改进的想法吗?使用ConcurrentHashMap
意味着您应该只信任文档中定义为原子的方法,例如:
putIfAbsent(K键,V值)
更换(K键,V键)
删除(K键,V值)
执行器,返回结果本身,以便线程在继续工作之前等待其完成:这样,您将以同步方式完成整个任务。一个新的尝试灵感来自:
现在我只需要这些ResultFuture
s中的一个HashMap
:
public Result execute(Query query) throws InterruptedException {
int id = atomicInteger.incrementAndGet();
ResultFuture resultFuture = new ResultFuture();
resultFutureMap.put(id, resultFuture);
query.executeAsyncWithId(id); // Probably returns before result is ready
try {
return resultFuture.get(); // Blocks until result is ready
} finally {
resultFutureMap.remove(id);
}
}
public void handleResult(Result result) {
int id = result.getId();
ResultFuture resultFuture = resultFutureMap.get(id);
if (resultFuture == null) {
return; // Nobody wants result
}
resultFuture.set(result);
}
我认为带有倒计时闩锁的版本可能是最好的解决方案。“实践中的Java并发”(Brian Goetz)实际上谈到了这一点(我认为他称之为值锁存)。它本质上是一种针对所设置值的一次性同步机制
虽然可以使用wait()-notifyAll()机制实现这样的值锁存,但使用CountDownLatch可以得到更简单的实现
CountDownLatch await()-countDown()方法提供了一个正确的发生之前关系。因此,请删除使用“latch”的代码,但不应在此函数中定义它。不过,我看不到任何东西会使它异步。实际上是底层系统执行异步查询。我已经将该方法重命名为“executeAsyncWithId”来澄清。嘿,我建议你将自己的答案作为答案发布,并接受它!应删除此答案,并将文本作为更新内容放在原始问题中。@James Black,完全可以提问并回答您自己的问题@hakos至少应该接受他自己的答案:)@Tim Bender-好的,仔细看后,我发现这是一个很好的答案,起初我认为这只是对原始示例的修改,只涉及一个HashMap。
public Result execute(Query query) throws InterruptedException {
int id = atomicInteger.incrementAndGet();
ResultFuture resultFuture = new ResultFuture();
resultFutureMap.put(id, resultFuture);
query.executeAsyncWithId(id); // Probably returns before result is ready
try {
return resultFuture.get(); // Blocks until result is ready
} finally {
resultFutureMap.remove(id);
}
}
public void handleResult(Result result) {
int id = result.getId();
ResultFuture resultFuture = resultFutureMap.get(id);
if (resultFuture == null) {
return; // Nobody wants result
}
resultFuture.set(result);
}