这是一个阻止系统(同步)。其背后的想法是:
这是尝试从缓存中获取文档的方法(简化)。
public dtoCache getDocumentFromCache(String cacheId)
{
dtoCache objCache = CacheFacade.getInstance().getCacheEntry(cacheId);
// If document not found in cache ...
if (objCache == null)
{
// If I'm the first, just return null (and the process to send the request
to the server will start outside this method). Otherwise block on this method.
if (!this.objLockAndAwait.lock(cacheId)) return null;
// At this point the first request with this 'cacheId' saved the document on cache,
so after awaking go to cache again because we will find the document there.
return (this.getDocumentFromCache(cacheId));
}
return (objCache);
}
'lock'方法非常简单,只需查询'mapCacheId'是否包含'cacheId'键即可。
public boolean lock(String cacheId)
{
// Get a 'lockObject' for this 'cacheId' and acquire it.
LockObject lockObject = this.stripedLock.getLockObject(cacheId);
lockObject.lock();
try
{
// Check if this 'cacheId' is going to the server right now. Two cases:
// 1. If the map does not contain this 'cacheId' --> don't block, I'm the
first --> return false and continue
// 1. If the map contains this 'cacheId' --> block on it.
if (this.mapCacheId.putIfAbsent(cacheId, (byte)0) != null)
{
lockObject.await(cacheId);
return true;
}
return false;
}
finally { lockObject.unlock(); }
}
这是“解锁”方法,每次从服务器发出请求时都会调用该方法。它会在'cacheId'上发出信号以唤醒所有被阻塞的线程。
public void unlock(String cacheId)
{
LockObject lockObject = this.stripedLock.getLockObject(cacheId);
lockObject.lock();
try
{
lockObject.signalAll(cacheId);
this.mapCacheId.remove(cacheId);
}
finally { lockObject.unlock(); }
}
现在,我需要重写此代码以使其异步。我不希望线程在等待条件下被阻塞,如果一个线程由于在“ mapCacheId”中找到了“缓存ID”而必须被阻塞,则我需要将该线程设为 释放以执行其他任务,并仅在通知发送给服务器的请求完成时才在回调中重新获取代码。
我正在检查“ CompletableFuture”,因为这似乎是解决方案,但是在玩了几天之后,我看不到如何修改代码以使其与CF异步。看来我需要这个N-1 CF来等待第一个CF-1的完成,但是CF api很复杂,我找不到任何类似的例子。
答案 0 :(得分:-1)
让class DtoCache extends CompletableFuture<Document>
。然后
// webapp receives a request
public void handleRequest(Request request) {
String cacheId = request.getCacheId();
boolean first = false;
DtoCache objCache;
synchronized(cache) {
objCache = cache.get(cacheId);
if (objCache == null) {
first = true;
objCache = new DtoCache();
cache.put(cacheId, objCache);
}
}
if (first) {
// only the first request asks the Api server
Document doc = askApiServer(cacheId);
// reply to our request
request.reply(doc);
// reply to the other requests
objCache.complete(doc);
} else {
// arrange an asynchronous reply to our request
objCache.thenApply(request::reply);
}