0

update(key, value)]メソッド [が を更新するマルチスレッド Java アプリケーションがありますConcurrentHashMap。キーごとに、マップに配置できるよりも多くの値が受信されるため、キーが更新されると、待機中のスレッドの最新の値のみを使用して、マップを再度更新する必要があります。それとも、待機中のスレッドが 1 つしかない場合に使用できるある種のロックがあるかもしれません - 最後にロックに到達したスレッド (既に待機しているスレッドを事実上破棄します)。マップ全体がロックされていないことが重要です。そのため、HashMapキー A で待機しているスレッドが存在する場合でも、キー B は更新されない限りキー B を更新できるようにする必要があるため、法線の周りで同期ブロックを使用していません。スレッドは、B に格納された値をすでに更新しています。

もっと簡潔に言えば、キーと値のペアが更新よりも速く受信されているマップを、最後に受信した値を次の更新として使用して更新するにはどうすればよいでしょうか? したがって、A が 1 に更新されるときに、5、3、6、8 の値が受信されます。これは、A の次の更新が 8 になることを意味します。

4

2 に答える 2

0

これは難しい問題であり、その難しさの根本は、更新が到着する順序を把握することにあります。

更新に関連付けられた (きめ細かい) タイムスタンプが既にある場合、解決策はかなり簡単です。

  1. Value実際の値とタイムスタンプを保持するクラスを定義します。setIfNewer(ActualValue v, Timestamp t)指定されたタイムスタンプがより新しい場合は、実際の値を更新する同期が必要です。
  2. としてマップを定義しますConcurrentHashMap<Key, Value>
  3. putIfAbsent値をマップに入れるために使用します。putIfAbsent()が null 以外の値を返す場合は、 を使用setIfNewer(...)して更新します。

これは、マップの更新が長期間維持できる場合にのみ機能することに注意してください。つまり、平均データ レートが高すぎて対処できないということはありません。

更新にタイムスタンプが関連付けられていない場合は、問題があります。更新についていくのが難しい場合は、到着時刻を正確に反映するタイムスタンプを更新に追加するのが難しくなります。つまり、更新が (事実上) 並べ替えられるリスクがあることを意味します。(この場合、問題を変更せずに問題を解決できるとは思いません。以下を参照してください。)

うまくいくかもしれないいくつかのこと:

  • ボトルネックが実際にどこにあるかを把握するために、いくつかのプロファイリング/パフォーマンス分析を行います。マップの更新をまったく行っていない可能性があります。(結局のところConcurrentHashMap、高度にスケーラブルになるように設計されています。)

  • スレッドとキー値の間に強い親和性がある場合は、1) スレッドごとの LRU マップを使用して各スレッドの更新を重複排除するか、2) タイムスタンプの代わりにスレッドごとのカウンターを使用することを試すことができます。

  • キースペースに基づいてマップを分割してみることができます。

  • プロファイリングと監視の報告内容に応じて、プロセッサやメモリを追加してみてください。

  • キースペースに基づいてアプリケーション全体を分割してみることができます。アプリケーションが追いつかないことが本当の問題である場合、これが唯一の可能なアプローチかもしれません。

于 2011-01-23T02:08:16.837 に答える
0

どうやってするの?

シーケンサーを実装するためのかなり単純な解決策があります。追加する各オブジェクトには、AtomicLong.getAndIncrement() のような smth を使用して構築時に割り当てられる long フィールドが必要です。

update はそのように見え、sync は必要ありません

Class Value{
private static final AtomicLong sequencer = new AtomicLong()
final long seq = sequencer.getAndIncrement():
public boolean equals(Object o){
  //include seq as well :)
}
....
}
ConcurrentMap map;
for (Value cur;;){
    cur = map.get(key);
    if (cur==null){
        if (null==(cur=map.putIfAbsent(key, value))){
            break;
        }
    }           
    if (cur.seq>=value.seq){
        break;
    }
    if (map.replace(key, cur, value))
        break;
}
于 2011-01-24T11:37:26.103 に答える