マルチスレッドモニタ統計カウンタ
2789 ワード
先月統計のカウンタを書きました.下はマルチスレッド同時アクセスでカウントされるクラスです.警報を監視するために、まずコードを貼って、暇があったら解読します.
import java.util.concurrent.atomic.AtomicReference;
public class RequestCounter {
private final AtomicReference<Accumulator> values;
private final int durationMS;
public RequestCounter(int durationMS) {
this.values = new AtomicReference<Accumulator>(new Accumulator());
this.durationMS = durationMS;
}
public long getCount() {
return getValidAccumulator().count;
}
public long getTotalCount() {
return getValidAccumulator().total;
}
public double getAverageTimeInMs() {
return getValidAccumulator().getAverageTimeMS();
}
public float getThroughput() {
Accumulator oldv = getValidAccumulator();
double elapsed = (System.currentTimeMillis() - oldv.startTimeMS) / 1000;
if (elapsed > 0f) {
return (float) (oldv.count / elapsed);
} else {
return -1f;
}
}
private Accumulator getValidAccumulator() {
Accumulator accum = values.get();
long now = System.currentTimeMillis();
if (now - accum.startTimeMS <= durationMS) {
return accum;
}
Accumulator newWithTotal = accum.newWithTotal();
if (values.compareAndSet(accum, newWithTotal)) {
return newWithTotal;
}
return values.get();
}
public void addRequest(long timeNS) {
for (int i = 0; i < 3; i++) {
Accumulator oldv = getValidAccumulator();
long startTimeMS = oldv.startTimeMS;
long count = oldv.count + 1;
long totalTimeNS = oldv.totalTimeMS + timeNS;
long total = oldv.total + 1;
if (values.compareAndSet(oldv, new Accumulator(startTimeMS, count,
totalTimeNS, total))) {
return;
}
}
}
private static class Accumulator {
final long startTimeMS;
final long count;
final long totalTimeMS;
final long total;
public Accumulator() {
this(System.currentTimeMillis(), 0, 0, 0);
}
public Accumulator newWithTotal() {
return new Accumulator(System.currentTimeMillis(), 0, 0, total);
}
public Accumulator(long startTimeMS, long count, long totalTimeMS,
long total) {
this.startTimeMS = startTimeMS;
this.count = count;
this.totalTimeMS = totalTimeMS;
this.total = total;
}
public double getAverageTimeMS() {
return count > 0 ? 1f * totalTimeMS / count : -0f;
}
}
}