我不太确定,但是:
It allows concurrent read access to
elements already in the cache. If the
element is null, other reads will
block until an element with the same
key is put into the cache.
这是不是意味着Hibernate会等到其他线程把对象放到缓存中?这是你观察到的,对吧?
Hib和缓存的工作原理如下:
> Hib获取对象的请求
> Hib检查对象是否在缓存中 – cache.get()
>不? Hib从DB加载对象并放入缓存 – cache.put()
所以如果对象不在高速缓存中(没有被一些以前的更新操作放在那里),Hib将等待1)永远.
我想你需要一个缓存变量,线程只能在短时间内等待一个对象.例如. 100毫秒.如果对象未到达,则线程应该为空(因此Hibernate将从DB加载对象并放入高速缓存).
其实,更好的逻辑是:
>检查另一个线程是否请求同一个对象
>如果为true,等待长(500ms)的对象到达
>如果不是true,请立即返回null
(我们永远不能等待2,因为线程可能无法将对象放入缓存 – 由于异常).
如果BlockingCache不支持此行为,则需要自己实现缓存.我以前做过,这并不困难 – 主要的方法是get()和put()(尽管API显然已经增长).
UPDATE
其实我只是读了BlockingCache的来源.它完全是我所说的 – 锁定并等待超时.因此,您不需要做任何事情,只需使用它…
public Element get(final Object key) throws RuntimeException, LockTimeoutException {
Sync lock = getLockForKey(key);
Element element;
acquiredLockForKey(key, lock, LockType.WRITE);
element = cache.get(key);
if (element != null) {
lock.unlock(LockType.WRITE);
}
return element;
}
public void put(Element element) {
if (element == null) {
return;
}
Object key = element.getObjectKey();
Object value = element.getObjectValue();
getLockForKey(key).lock(LockType.WRITE);
try {
if (value != null) {
cache.put(element);
} else {
cache.remove(key);
}
} finally {
getLockForKey(key).unlock(LockType.WRITE);
}
}
所以这很奇怪,这对你来说不行.告诉我一些:在你的代码这个地方:
Ehcache cache = manager.getEhcache("foo");
是否同步?如果多个请求同时出现,那么只有一个缓存实例呢?