当前位置: 首页 > 知识库问答 >
问题:

如何计算给定间隔内的事件数?

洪旻
2023-03-14

我需要知道不同事件发生的频率。例如,在过去 15 分钟内发生了多少个 HTTP 请求。由于可能有大量的事件(数百万个),因此必须使用有限的内存量。

Java中有什么util类可以做到这一点吗?

如何在Java中实现这个自我?

理论用法代码可以如下所示:

FrequencyCounter counter = new FrequencyCounter( 15, TimeUnit.Minutes );
...
counter.add();
...
int count = counter.getCount();

编辑:它必须是一个实时值,可以在一分钟内更改数千次,并且将在一分钟内查询数千次。基于数据库或文件的解决方案是不可能的。

共有3个答案

勾喜
2023-03-14

预约遗嘱执行人服务怎么样?

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
                      );

这是一个有点复杂的方法。

我可能会有一个列表

郭逸清
2023-03-14

我能想到的最好的实现方法是使用另一个“计时”线程。< 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();
    }
}
欧镜
2023-03-14

这是我对这样一个计数器的实现。默认精度的内存使用少至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 输出类似于,带有单位排序。 你只需要将该映射转换为用户友好的字符串即可。 警告 上面的代码片段计算了两个瞬间之间的简单差异。它可以在夏令开