【发布时间】:2011-12-22 14:24:44
【问题描述】:
我编写了一个股票市场模拟器,它使用ConcurrentHashMap 作为缓存。
缓存包含大约 75 个元素,但它们的更新和检索速度非常快(大约每秒 500 次)。
这是我所做的:
线程 1:
连接到外部系统,该系统为我提供给定股票代码的流式报价。
线程 2(回调线程):
等待外部系统将数据传递给它。一旦它得到数据,它就会解析它,创建一个不可变的 DataEntry 对象,缓存它并向 thread3 发送信号。
线程 3(消费者线程): 收到信号后,从缓存中检索 DataEntry 并使用它。 (不让线程2直接向线程3推送数据是任务的一部分)。
public final class DataEntry{
private final String field1;
private final String field2;
//...
private final String field25;
// Corresponding setters and getters
}
public final class Cache{
private final Map<String, DataEntry> cache;
public Cache( ){
this.cache = new ConcurrentHashMap<String, DataEntry> ( 65, 0.75, 32 );
}
// Methods to update and retrieve DataEntry from the cache.
}
通过分析器运行它后,我注意到我正在创建一个 lot 的 DataEntry 对象。因此伊甸园很快就会被填满。
所以,我正在考虑通过以下方式调整设计:
a) 使DataEntry 类可变。
b) 使用空的DataEntry 对象预先填充缓存。
c) 当更新到达时,从地图中检索DataEntry 对象并填充字段。
这样,DataEntry 对象的数量将是常数并且等于元素的数量。
我的问题是:
a) 此设计是否存在我通过使DataEntry 可变而引入的任何并发问题。
b)我还能做些什么来优化缓存吗?
谢谢。
【问题讨论】:
-
您可以每秒访问超过 100 万次 ConcurrentHasMap,如果您仅每秒访问 500 次,它不会产生太大影响。
-
如果您希望有接近 16 个或更多内核一次访问 Map,我只会增加分区大小。如果您使用少于 4 个内核一次访问地图(并且不执行任何其他操作),则不太可能产生太大影响。
-
为什么快速填满伊甸园会成为问题?您是否真的因为 Eden GC 遇到问题?
-
在 Java 中分配短期对象非常便宜,因此我不会担心。您可以重复使用数据条目,但仍然必须重新插入它们,所以我怀疑这会产生很大的不同。
标签: java caching optimization memory concurrenthashmap