18

long次の要件/事実を持つタイプのカウンターが必要です。

  • カウンターのインクリメントには、できるだけ時間がかからないようにする必要があります。
  • カウンターは1つのスレッドによってのみ書き込まれます。
  • カウンターからの読み取りは別のスレッドで行われます。
  • カウンターは定期的に(1秒間に数千回も)インクリメントされますが、5秒ごとに1回だけ読み取られます。
  • 正確な精度は必須ではありません。カウンターのサイズの大まかなアイデアだけで十分です。
  • カウンターがクリアされたり、デクリメントされたりすることはありません。

これらの要件に基づいて、どのようにカウンターを実装することを選択しますか?単純なlongものとして、volatile longまたはを使用してAtomicLong?なんで?

現時点では、私は持ってvolatile longいますが、別のアプローチがより良いかどうか疑問に思っていました。私はまた、++counterとは対照的に行うことによって私の長い時間を増やしていcounter++ます。割り当てが行われていないので、これは本当にもっと効率的ですか(私は他の場所で信じるように導かれています)?

4

5 に答える 5

12

これらの一連の要件を考えると、volatilelong で十分だと思います。カウンターは非volatilelong では正しくありませんが、その場合、リーダーは古い情報を読み取っている可能性があります。

1 つの問題は、宣言されていない場合、 JVM 仕様により、a への読み取りと書き込みがアトミックである必要longないことです。これは、書き込みスレッドが値の一部を更新し、他の部分を更新していない間に値を読み取ると、読み取りスレッドがかなり架空の値を取得できることを意味します。volatile

JVM は式の値が使用されなくなったことを認識し、この場合は 2 つが同等であるため、++counterとの違いcounter++おそらく無関係です。

于 2010-03-15T15:09:52.120 に答える
5

Java 8 では、スレッドの競合が多い AtomicLong よりもさらに優れた LongAdder を使用します。

LongAdder JavaDoc:

通常、このクラスは、きめ細かな同期制御ではなく、統計の収集などの目的で使用される共通の合計を複数のスレッドが更新する場合、AtomicLong よりも適しています。更新の競合が少ない場合、2 つのクラスは同様の特性を持っています。ただし、競合が多い場合、このクラスの予想スループットは大幅に高くなりますが、スペースの消費量が増えます。

于 2015-08-04T07:19:03.113 に答える
0

この記事では、カウンターを実装するための可能な方法について説明します。この実装はあなたのために働くはずだと思います

class LessNaiveVolatieIdGenerator {
private static volatile long id = 0;
public static long nextId() {
    long nextId = (id = id + 1); // or nextId = id++;
    return nextId;
}

}

于 2011-12-01T01:05:55.313 に答える
0

プログラムの稼働時間の要件は何ですか?揮発性のないintとracy-readsで間に合わせることができますか?

于 2010-03-15T15:32:18.420 に答える
0

10^4 増分/秒は、100 マイクロ秒ごとに 1 です。効率は問題ではありませんが、原子性が問題になる可能性があります。あなたはそれを 2 部持っているかもしれません。

于 2010-03-15T17:26:48.333 に答える