tre*_*sta 5 java collections performance
我有一个特定的用例,但无法确定要使用的正确数据结构.
我有一个线程可以将对象保存到HashMap中.类似于市场数据的东西,你有很高和未知的滴答频率.
另一个线程不断按顺序读取此映射以更新Price对象和查询.对于给定周期中的相同密钥,查询可以是多次.读取和写入非常频繁,但读取线程仅对最新可用数据感兴趣,这些数据已完全更新,并且在写入完成之前不一定会阻塞.
我希望您对这种用例的理想数据结构有所了解.是否有比ConcurrentHashMap更好的实现?
谢谢
一种方法是写时复制方案,如下所示:
public class Prices {
private volatile Map<String, Integer> prices = Collections.emptyMap();
public void putPrice(String ticker, int price) {
HashMap<String, Integer> newPrices = new HashMap<String, Integer>(prices);
newPrices.put(ticker, price);
prices = newPrices;
}
public Integer getPrice(String ticker) {
return prices.get(ticker);
}
}
Run Code Online (Sandbox Code Playgroud)
这对于获取来说具有最小的开销——从易失性中读取一次,然后进行正常的哈希查找。然而,它对于 put 来说有很大的开销 - 创建一个全新的映射,再加上写入一个易失性。如果您的读写比率很高,这可能仍然是一个很好的权衡。
您可以通过仅在实际需要添加新条目时更改映射来改进这一点,而不是更新现有条目;您可以通过使用可变值来实现这一点:
public class Prices {
private volatile Map<String, AtomicInteger> prices = Collections.emptyMap();
public void putPrice(String ticker, int price) {
AtomicInteger priceHolder = prices.get(ticker);
if (priceHolder != null) {
priceHolder.set(price);
}
else {
HashMap<String, AtomicInteger> newPrices = new HashMap<String, AtomicInteger>(prices);
newPrices.put(ticker, new AtomicInteger(price));
prices = newPrices;
}
}
public Integer getPrice(String ticker) {
AtomicInteger priceHolder = prices.get(ticker);
if (priceHolder != null) return priceHolder.get();
else return null;
}
}
Run Code Online (Sandbox Code Playgroud)
我不确定 an 的性能特征AtomicInteger是什么;这可能比看起来慢。假设速度AtomicInteger不是不合理的慢,这应该相当快 - 它涉及从易失性中读取两次,加上每次获取的正常哈希查找,以及从易失性中读取,哈希查找,以及对易失性进行单次写入以更新现有的价格。它还涉及复制地图以添加新价格。然而,在典型的市场中,这种情况并不经常发生。