static V synchronizedLoad(CacheConfig config, AbstractCacheabstractCache,
K key, Function newLoader, ConsumercacheUpdater) {
ConcurrentHashMap loaderMap =abstractCache.initOrGetLoaderMap();
Object lockKey=buildLoaderLockKey(abstractCache, key);while (true) {boolean create[] = new boolean[1];
LoaderLock ll= loaderMap.computeIfAbsent(lockKey, (unusedKey) ->{
create[0] = true;
LoaderLock loaderLock= newLoaderLock();
loaderLock.signal= new CountDownLatch(1);
loaderLock.loaderThread=Thread.currentThread();returnloaderLock;
});if (create[0] || ll.loaderThread ==Thread.currentThread()) {try{
V loadedValue=newLoader.apply(key);
ll.success= true;
ll.value=loadedValue;
cacheUpdater.accept(loadedValue);returnloadedValue;
}finally{if (create[0]) {
ll.signal.countDown();
loaderMap.remove(lockKey);
}
}
}else{try{
Duration timeout=config.getPenetrationProtectTimeout();if (timeout == null) {
ll.signal.await();
}else{boolean ok =ll.signal.await(timeout.toMillis(), TimeUnit.MILLISECONDS);if(!ok) {
logger.info("loader wait timeout:" +timeout);returnnewLoader.apply(key);
}
}
}catch(InterruptedException e) {
logger.warn("loader wait interrupted");returnnewLoader.apply(key);
}if(ll.success) {return(V) ll.value;
}else{continue;
}
}
}
}static classLoaderLock {
CountDownLatch signal;
Thread loaderThread;volatile booleansuccess;volatileObject value;
}