这是一个阻塞系统(同步)。其背后的想法是:
这是一种尝试从缓存中获取文档的方法(简化)。
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”中找到'cache id‘而必须被阻塞,我需要释放这个线程来接受另一个任务,并且只有在通知发送到服务器的请求完成后,才会在回调中重新捕获代码。
我正在检查'CompletableFuture',因为它似乎是解决这个问题的方法,但是在玩了几天之后,我无法看到如何修改代码,使其与CF异步。看来我需要这个N-1CF来等待第一个CF的完成,但是CF很复杂,我找不到任何类似的例子。
发布于 2018-08-18 19:17:01
让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);
}
https://stackoverflow.com/questions/51910263
复制