我编写了一个股票市场模拟器,它使用 ConcurrentHashMap
作为缓存。
缓存保存了大约 75 个元素,但它们的更新和检索速度非常快(大约每秒 500 次)。
这是我所做的:
主题 1:
连接到外部系统,该系统为我提供给定股票代码的流式报价。
线程2(回调线程):
等待外部系统将数据传送给它。一旦获取数据,它就会解析它,创建一个不可变的 DataEntry 对象,缓存它并向 thread3 发送信号。
线程 3(消费者线程): 收到信号后,从缓存中检索 DataEntry 并使用它。 (不让thread2直接向thread3推送数据是任务的一部分)。
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) 当更新到达时,从 map 中检索 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
这远远超出了您所使用的访问速率。
如果你想减少垃圾,你可以使用可变对象和原语。因此,我会避免使用字符串(因为您的字符串似乎比数据条目多得多)
关于java - 编写高性能Cache,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8605220/