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);
}
}
これには、getのオーバーヘッドが最小限に抑えられます。1つは揮発性から読み取り、次に通常のハッシュルックアップです。ただし、プットにはかなりのオーバーヘッドがあります。まったく新しいマップの作成に加えて、揮発性ファイルへの書き込みです。読み取りと書き込みの比率が高い場合でも、これは適切なトレードオフになる可能性があります。
これを改善するには、既存のエントリを更新するのではなく、実際に新しいエントリを追加する必要があるときにのみマップを変更します。可変値を使用することでこれを実現できます。
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;
}
}
のパフォーマンス特性が何であるかはわかりませんAtomicInteger
。これは見た目よりも遅い可能性があります。不当に遅いと仮定するとAtomicInteger
、これはかなり速いはずです-揮発性からの2回の読み取りと、取得ごとの通常のハッシュルックアップ、および揮発性からの読み取り、ハッシュルックアップ、および既存の更新のための揮発性への1回の書き込みが含まれます価格。それでも、新しい価格を追加するためにマップを複製する必要があります。ただし、一般的な市場では、それは頻繁には発生しません。