我写了一个使用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(因为您似乎拥有比数据条目更多的字符串)

07-28 07:02