Java计数器,最后一小时的值

时间:2016-07-07 07:44:31

标签: java counter

我需要一个计数器,当某些任务完成时,计数器会增加。我们只需要最后一小时的值,即窗口将移动而不是静态时间。

最好的方法是什么?我能想到的一种方法是使用一个大小为60的数组,每分钟一个并更新相应分钟的条目,并在get()上执行总计。在转到新的一分钟时,阵列将被重置。

有更好的解决方案吗?任何基于时间的计数器实现可用吗?

3 个答案:

答案 0 :(得分:2)

您可以实现某种类型的数组,它会为您提供最佳值(并可用于绘制图形等)。但是如果你有兴趣以单值进行,那就有一个技巧可以得到适当的近似值。它用于例如unix上的loadavg计算 https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation

  

系统将负载平均值计算为负载数的指数衰减/加权移动平均值。平均负载的三个值是指系统运行的过去的一分钟,五分钟和十五分钟。[2]

     

从数学上讲,自系统启动以来,所有三个值始终平均所有系统负载。它们都呈指数衰减,但它们以不同的速度衰减:它们分别在1分钟,5分钟和15分钟后以指数方式衰减。因此,1分钟的负载平均值将比最后一分钟加载63%(更确切地说:1 - 1 / e),加上自启动以来排除最后一分钟的负载的37%(1 / e)。对于5分钟和15分钟的平均负荷,在5分钟和15分钟内分别计算相同的63%/ 37%比率。因此,技术上准确的是,1分钟的平均负载仅包括最后60秒的活动(因为它仍然包括过去37%的活动),但这主要包括最后一分钟。

计算单个值的移动平均线 - 有多种可能性,详细描述,这里有一些证明 https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average

最适合您的用例可能就是这个 https://en.wikipedia.org/wiki/Moving_average#Application_to_measuring_computer_performance

equation

答案 1 :(得分:2)

为此,我编写了Java类DecayingCounter

它使用以下公式来实现指数时间衰减计数器:

tau = halfLifeInSeconds / Math.log(2.0)
value *= Math.exp(deltaTimeInNanos * -1E-9 / tau)

答案 2 :(得分:1)

对于更简单的技术,但很好的阅读Artur!

您可以在每次需要时使用List来存储。然后在获得列表时过滤那些。

private static List<Long> counter = new LinkedList<Long>(); //Thanks to Artur to point that out. (Faster but a Queue takes more memory)
public static final long FILTER_TIME = 1000*60*60;

public static void add(){
    add(System.currentTimeMillis());
}

public static List<Long> get(){
    filter();
    return counter;
}

private static void filter(){
    int length = counter.size();
    long lastHour = System.currentTimeMillis() - 1000*60*60;

    //trim from left until value is correct or list is empty
    while(length > 0 && counter.get(0) < lastHour){
        counter.remove(0);
        length--;
    }
}

结果将是一个列表(由于add方法只添加currentTime而排序)没有旧值。这是基本的实现,可以使用更好的技术,但需要快速解决方案。这可以做到。

过滤器在getter上完成。这意味着如果很少进行此读取,则列表可能会爆炸。所以这也可以在add方法中完成。