我需要知道不同事件发生的频率。例如,在过去 15 分钟内发生了多少个 HTTP 请求。由于可能有大量的事件(数百万个),因此必须使用有限的内存量。
Java中有什么util类可以做到这一点吗?
如何在Java中实现这个自我?
理论用法代码可以如下所示:
FrequencyCounter counter = new FrequencyCounter( 15, TimeUnit.Minutes );
...
counter.add();
...
int count = counter.getCount();
编辑:它必须是一个实时值,可以在一分钟内更改数千次,并且将在一分钟内查询数千次。基于数据库或文件的解决方案是不可能的。
预约遗嘱执行人服务怎么样?
class TimedValue{
int startValue;
int finishedValue;
TimedValue(int start){
startValue = start;
}
}
List<TimedValue> intervals = new CopyOnWriteArrayList<>();
//then when starting a measurement.
TimeValue value = new TimedValue();
//set the start value.
Callable<TimedValue> callable = ()->{
//performs the task.
value.setValueAtFinish(getCount());
return value;
}
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
ScheduledFuture<TimedValue> future = executor.schedule(
callable,
TimeUnit.MINUTES,
15);
executor.schedule(()->itervals.add(
future.get(),
TimeUnit.MINUTES,
future.getDelay(TimeUnit.MINUTES
);
这是一个有点复杂的方法。
我可能会有一个列表
我能想到的最好的实现方法是使用另一个“计时”线程。< br >如果您担心内存量,可以为< code > events counter (< code > Integer。MAX_VALUE似乎是自然的选择)。
下面是一个实现示例,该实现也是线程安全的:
public class FrequencyCounter {
private AtomicInteger eventsCounter = new AtomicInteger(0);
private int timeCounter;
private boolean active;
public FrequencyCounter(int timeInSeconds) {
timeCounter = timeInSeconds;
active = true;
}
// Call this method whenever an interesting event occurs
public int add() {
if(active) {
int current;
do {
current = eventsCounter.get();
} while (eventsCounter.compareAndSet(current, current + 1));
return current + 1;
}
else return -1;
}
// Get current number of events
public int getCount() {
return eventsCounter.get();
}
// Start the FrequencyCounter
public void run() {
Thread timer = new Thread(() -> {
while(timeCounter > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
timeCounter --;
}
active = false;
});
timer.start();
}
}
这是我对这样一个计数器的实现。默认精度的内存使用少至100字节。内存使用与事件计数无关。
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* A counter that counts events within the past time interval. All events that occurred before this interval will be
* removed from the counter.
*/
public class FrequencyCounter {
private final long monitoringInterval;
private final int[] details;
private final AtomicInteger currentCount = new AtomicInteger();
private long startInterval;
private int total;
/**
* Create a new instance of the counter for the given interval.
*
* @param interval the time to monitor/count the events.
* @param unit the time unit of the {@code interval} argument
*/
FrequencyCounter( long interval, TimeUnit unit ) {
this( interval, unit, 16 );
}
/**
* Create a new instance of the counter for the given interval.
*
* @param interval the time to monitor/count the events.
* @param unit the time unit of the {@code interval} argument
* @param precision the count of time slices for the for the measurement
*/
FrequencyCounter( long interval, TimeUnit unit, int precision ) {
monitoringInterval = unit.toMillis( interval );
if( monitoringInterval <= 0 ) {
throw new IllegalArgumentException( "Interval mus be a positive value:" + interval );
}
details = new int[precision];
startInterval = System.currentTimeMillis() - monitoringInterval;
}
/**
* Count a single event.
*/
public void increment() {
checkInterval( System.currentTimeMillis() );
currentCount.incrementAndGet();
}
/**
* Get the current value of the counter.
*
* @return the counter value
*/
public int getCount() {
long currentTime = System.currentTimeMillis();
checkInterval( currentTime );
long diff = currentTime - startInterval - monitoringInterval;
double partFactor = (diff * details.length / (double)monitoringInterval);
int part = (int)(details[0] * partFactor);
return total + currentCount.get() - part;
}
/**
* Check the interval of the detail counters and move the interval if needed.
*
* @param time the current time
*/
private void checkInterval( final long time ) {
if( (time - startInterval - monitoringInterval) > monitoringInterval / details.length ) {
synchronized( details ) {
long detailInterval = monitoringInterval / details.length;
while( (time - startInterval - monitoringInterval) > detailInterval ) {
int currentValue = currentCount.getAndSet( 0 );
if( (total | currentValue) == 0 ) {
// for the case that the counter was not used for a long time
startInterval = time - monitoringInterval;
return;
}
int size = details.length - 1;
total += currentValue - details[0];
System.arraycopy( details, 1, details, 0, size );
details[size] = currentValue;
startInterval += detailInterval;
}
}
}
}
}
假设您有一个间隔列表,例如[(0 4),(1 3),(2 5),(2 6)]。此列表未排序。然后给您一个范围,如[1 5]。您必须返回适合范围内的间隔数。在这个问题中,它将返回2。((1 3)和(2 5)) 间隔列表保持不变,但我们最多得到100000个查询,每个查询由一个范围组成。对于每个范围查询,我们必须返回适合其中的间隔数。 在研究之后,我读到了间隔树。但是,您只能查询与任何给定范围重叠的间
问题内容: 使用Java访问系统时钟的简便方法是什么,以便我可以计算事件的经过时间? 问题答案: 我会避免使用它来测量经过时间。返回“壁钟”时间,该时间可能会更改(例如:夏时制,管理员用户更改时钟)并会使您的间隔测量值偏斜。 另一方面,返回自“某个参考点”(例如,JVM启动)以来的纳秒数,因此不会受到系统时钟变化的影响。
问题内容: 我有一条流经多个系统的消息,每个系统都会记录消息的进入和退出以及时间戳和uuid messageId。我通过以下方式提取所有日志: 结果,我现在有以下事件: 我想生成一个报告(最好是堆积的条或列),用于每个系统的时间: 做这个的最好方式是什么?Logstash过滤器?kibana计算字段? 问题答案: 您只能使用Logstash 过滤器来实现此目的,但是,您必须实质性地重新实现该过滤器
问题内容: 如果我有两个日期,获取这两个日期之间的天数的最佳方法是什么? 问题答案: 如果你有两个日期对象,则可以减去它们,从而计算出一个对象。
问题内容: 在java中如何计算两个日期的间隔? 问题答案: 简单差异(无lib) 然后你可以致电: 以分钟为单位获取两个日期的差异。 ,一个标准的Java枚举,范围从nanos到数天。 可读的差异(无lib) http://ideone.com/5dXeu6 输出类似于,带有单位排序。 你只需要将该映射转换为用户友好的字符串即可。 警告 上面的代码片段计算了两个瞬间之间的简单差异。它可以在夏令开