【发布时间】:2019-04-23 16:36:21
【问题描述】:
我有一个 ConcurrentHashMap 用作内存存储(或缓存,你可能会说)
我想要实现的是:同时检查一个项目是否“准备好”,如果是,则将其从地图中删除(+将其返回给调用者)。没有直接的方法可以让我做到这一点。
我想出的唯一解决方案是有一个ItemContainer,它将包含项目和元数据(isReady 字段)。在每次访问时,我都必须应用 merge 或 compute 操作。基本上在每次访问/检查时替换对象的容器。
问题:
- 我的解决方案看起来合理吗?
- 有没有实现类似功能的优秀库?
我按要求添加了“样板”代码:
public class Main {
public static void main(String[] args) {
Storage storage = new Storage();
storage.put("1", new Record("s", 100));
storage.put("2", new Record("s", 4));
storage.removeIf("1", Main::isReady);
}
public static boolean isReady(Record record) {
return record.i > 42;
}
public static class Record {
public Record(String s, Integer i) {
this.s = s;
this.i = i;
}
String s;
Integer i;
}
public static class Storage {
ConcurrentHashMap<String, Record> storage = new ConcurrentHashMap<>();
public void put(String key, Record record) {
storage.put(key, record);
}
public Record removeIf(String key, Function<Record, Boolean> condition) {
return null; // TODO: implement
}
}
}
其他解决方案(需要权衡):
- 始终检查
remove(),然后将merge()返回地图。 - 使用具有一些合理的项目疏散策略(即 LRU)的缓存并仅检查已疏散的项目。
基于@ernest_k 解决方案:
public Record removeIf(String key, Predicate<Record> condition) {
AtomicReference<Record> existing = new AtomicReference<>();
this.storage.computeIfPresent(key, (k, v) -> {
boolean conditionSatisfied = condition.test(v);
if (conditionSatisfied) {
existing.set(v);
return null;
} else {
existing.set(null);
return v;
}
});
return existing.get();
}
【问题讨论】:
-
描述并没有给我们你当前代码的想法。请张贴代码。
-
@ernest_k,我真的相信描述足够详细,可以回答我的问题 + 我还没有真正的工作代码。您希望我详细说明某些事情吗?
-
我可以准备一些代码
-
“同时检查一个项目是否准备就绪” - 项目是
Map的键还是值? item 是否必须在它准备好 后尽快从Map中删除?如果没有,您能否有一些任务在整个地图上进行同步、迭代并删除所有准备就绪的items? -
也许你可以看看 jcache javadoc,见static.javadoc.io/javax.cache/cache-api/1.0.0/javax/cache/… - (你可以使用 registerCacheEntryListener 将监听器添加到缓存中),例如。 Ehcache 是一个 jcache 实现
标签: java multithreading caching data-structures thread-safety