我写了一个使用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.
}
通过事件探查器运行它之后,我注意到我正在创建很多
DataEntry
对象。因此,伊甸园很快就装满了。因此,我正在考虑通过以下方式对设计进行调整:
a)使
DataEntry
类可变。b)用空的
DataEntry
对象预填充缓存。c)更新到达时,从地图中检索
DataEntry
对象并填充字段。这样,
DataEntry
对象的数量将是恒定的,并且等于元素的数量。我的问题是:
a)此设计是否存在我可能通过使
DataEntry
可变而引入的并发问题。b)我还有什么可以做的来优化缓存?
谢谢。
最佳答案
我不会担心ConcurrentHashMap的速度
Map<Integer, Integer> map = new ConcurrentHashMap<>();
long start = System.nanoTime();
int runs = 200*1000*1000;
for (int r = 0; r < runs; r++) {
map.put(r & 127, r & 127);
map.get((~r) & 127);
}
long time = System.nanoTime() - start;
System.out.printf("Throughput of %.1f million accesses per second%n",
2 * runs / 1e6 / (time / 1e9));
版画
Throughput of 72.6 million accesses per second
这远远超出了您似乎正在使用的访问速率。
如果要减少垃圾,可以使用可变对象和基元。因此,我将避免使用String(因为您似乎拥有比数据条目更多的字符串)