マルチスレッドモニタ統計カウンタ


先月統計のカウンタを書きました.下はマルチスレッド同時アクセスでカウントされるクラスです.警報を監視するために、まずコードを貼って、暇があったら解読します.
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;
		}
	}
}