我很难给它起一个合适的标题,但举个例子应该会简单得多,假设我有这样的例子:
final class Cache {
private static final ConcurrentHashMap<String, List<String>> CACHE = ...
static String byName(String name) {
return CACHE.computeIfAbsent(name, x -> // some expensive operation)
}
}
这个想法可能是微不足道的,它充当一个LoadingCache,很像Guava或咖啡因(实际上它更复杂,但这与问题无关)。
我希望能够判断这是第一次加载该高速缓存,还是读取了现有Map。目前,我这样做:
final class Cache {
private static final ConcurrentHashMap<String, List<String>> CACHE = ...
static String byName(String name) {
boolean b[] = new boolean[1];
List<String> result = CACHE.computeIfAbsent(name, x -> {
b[0] = true;
// some expensive operation)
});
if(b[0]) {
// first load into the cache, do X
} else {
// do Y
}
return result;
}
}
这是可行的,但我担心我错过了ConcurrentHashMap
可以为我提供的东西,它可以让我做同样的事情。谢谢。
2条答案
按热度按时间rta7y2nd1#
如果你想避免使用单元素数组将数据从lambda中传递出去(我更愿意使用
AtomicReference
或AtomicBoolean
),你可以使用一个有状态回调对象,它不会改变你代码的行为或设计,但可以被认为是更干净和更面向对象的。或者把它翻过来:
构造和加载可以封装在静态方法中:
jei2mxaa2#
我可以想到几种使用
ConcurrentHashMap
API的方法。这两种方法都使用了一个有副作用的Map函数。其思想是函数记录 * 是否 * 调用了它,或者 * 使用了什么参数 * 调用了它。computeIfAbsent
的规范说明只有在键不存在时才调用Map函数。或者,compute
的规范说明如果键是参数,则使用null
参数调用Map函数。在任一种情况下,如果您通过(比如)Map器函数/对象的字段,您可以确定该高速缓存条目是否已经存在。要使此函数线程安全,需要创建mapper函数的一个新示例(线程限制的)。