流数据的理想Java数据结构

tre*_*sta 5 java collections performance

我有一个特定的用例,但无法确定要使用的正确数据结构.

我有一个线程可以将对象保存到HashMap中.类似于市场数据的东西,你有很高和未知的滴答频率.

另一个线程不断按顺序读取此映射以更新Price对象和查询.对于给定周期中的相同密钥,查询可以是多次.读取和写入非常频繁,但读取线程仅对最新可用数据感兴趣,这些数据已完全更新,并且在写入完成之前不一定会阻塞.

我希望您对这种用例的理想数据结构有所了解.是否有比ConcurrentHashMap更好的实现?

谢谢

Tom*_*son 1

一种方法是写时复制方案,如下所示:

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不是不合理的慢,这应该相当快 - 它涉及从易失性中读取两次,加上每次获取的正常哈希查找,以及从易失性中读取,哈希查找,以及对易失性进行单次写入以更新现有的价格。它还涉及复制地图以添加新价格。然而,在典型的市场中,这种情况并不经常发生。