Вот что я в итоге написал.
package com.example;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BucketCounter {
private final Lock rollLock = new ReentrantLock();
private final int[] bucketSizes;
private final int[] buckets;
private final int[] intervals;
private final AtomicInteger incoming = new AtomicInteger(0);
public BucketCounter(int... bucketSizes) {
if (bucketSizes.length < 1) {
throw new IllegalArgumentException("Must specify at least one bucket size");
}
this.bucketSizes = bucketSizes;
this.buckets = new int[bucketSizes.length];
Arrays.sort(bucketSizes);
if (bucketSizes[0] < 1) {
throw new IllegalArgumentException("Cannot have a bucket of size < 1");
}
intervals = new int[bucketSizes[bucketSizes.length - 1]];
}
public int count(int n) {
return incoming.addAndGet(n);
}
public int[] roll() {
final int toAdd = incoming.getAndSet(0);
rollLock.lock();
try {
final int[] results = new int[buckets.length];
for (int i = 0, n = buckets.length; i < n; i++) {
results[i] = buckets[i] = buckets[i] - intervals[bucketSizes[i] - 1] + toAdd;
}
System.arraycopy(intervals, 0, intervals, 1, intervals.length - 1);
intervals[0] = toAdd;
return results;
} finally {
rollLock.unlock();
}
}
}
Инициализировать его, передавая различные приращения времени (например, 1, 5, 30). Затем организуйте фоновый поток, чтобы вызвать roll()
каждый «период времени». Если вы вызываете его каждую секунду, ваши ведра составляют 1, 5 и 30 секунд. Если вы вызываете его каждые 5 секунд, то ваши ведра составляют 5, 25 и 150 секунд и т. Д. В принципе, ведра выражаются в «количестве раз roll()
называется»).
roll()
также возвращает вам массив текущих подсчетов для каждого ведра. Обратите внимание, что эти числа являются сырыми подсчетами и не усредняются за промежуток времени. Вам нужно будет сделать это подразделение самостоятельно, если вы хотите измерить «ставки», а не «считать».
И, наконец, каждый раз, когда происходит событие, звоните count()
. Я создал систему с несколькими из них, и я вызываю count(1)
на каждое сообщение, чтобы подсчитывать входящие сообщения, count(message.size())
на каждое сообщение, чтобы подсчитывать входящие байтовые ставки и т. Д.
Надеюсь, что это поможет.
Прогресс в этом вопросе? У меня есть по существу одно и то же требование. – sceaj
В итоге я написал свой собственный. Я отправлю его в ответ. – dty