2016-07-07 8 views
2

特定のタスクが完了すると増分するカウンタが必要です。最後に1時間のの値が必要です。つまり、ウィンドウは静的な時間ではなく移動します。最後の1時間の値を持つJavaカウンタ

これについてはどのような方法が最適ですか?私が考えることのできる1つの方法は、サイズ60の配列を1分ごとに1つずつ持ち、それぞれの分のエントリを更新し、get()で合計します。新しい分に切り替えると、アレイがリセットされます。

もっと良い解決策はありますか?利用可能なカウンターの実装はいつでも可能ですか?

+2

Downvoter、ケア:

それは指数関数的に時間的に減衰するカウンタを実装するには、次の数式を使用していますか? – rajesh

+0

'AtomicInteger'カウンタとタイマーサービスを作成します。タスクが完了するとカウンターをインクリメントします。タイマサービスを使用すると、1時間ごとにカウンタがゼロにリセットされます。古いデータを保存したい場合は、カウンターをリセットする前に ''をいくつかのマップに入れてください。 – sauumum

+0

なぜ1分ごとのスケールでそれを数えますか?単なる(おそらく長い)整数を使用するのはなぜですか? – Tiina

答えて

2

あなたは最良の値を与える(そしてグラフなどの描画に使用できる)何らかの種類の配列を実装することができます。しかし、あなたが単価値でそれをすることに興味があるなら、適切な近似を得るためのトリックがあります。システムが負荷値の指数的に重み付けされ/減衰移動平均として、平均負荷を算出UNIX https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation

にloadavg計算の例のために使用されます。負荷平均の3つの値は、過去1,5、および15分のシステム操作を参照しています。[2]

3つの値はすべて、システムが起動してからのシステム負荷の平均値です。それらはすべて指数関数的に減衰しますが、速度が異なると減衰します.1,5,5分後に指数関数的に減衰します。したがって、1分間の負荷平均は、直前の負荷から63%(より正確には1 - 1/e)と、最後の1分間を除いて起動してから負荷の37%(1/e)を加算します。 5分間および15分間の負荷平均では、同じ63%/ 37%の比がそれぞれ5分および15分で計算されます。したがって、1分間の負荷平均には過去60秒のアクティビティだけが含まれています(これまでの37%のアクティビティはまだ含まれているため)。

単一の値で移動平均を計算 - あなたのユースケースのためのいくつかの証拠で詳細に説明し、複数の可能性が、ここにあります https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average

ベスト1は、おそらくこの1 https://en.wikipedia.org/wiki/Moving_average#Application_to_measuring_computer_performance

equation

です
+0

私はこれを確認してください、ありがとう。 – rajesh

1

簡単なテクニックではありますが、Arturからの読み込みは素晴らしいです!

リストを使用するだけで、必要なときに毎回保存することができます。次に、リストを取得したときにフィルタリングします。

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を追加するため、ソートされた)リストになります。これは基本的な実装であり、より良い技術を使用することができますが、迅速な解決策です。これはそれを行うことができます。

フィルタはゲッタで実行されます。これは、この読みがめったに行われない場合、リストが長さに爆発する可能性があることを意味します。これはaddメソッドでも実行できます。

+0

古い値を削除するのはおそらく良いでしょう。さもなければ、リストは永遠に成長します。 –

+0

これはsubListを介して行われますが、返す前にsetcounterを実行しますが、これについての段落を追加しました。 – AxelH

+0

あなたはサブリストが元の配列を参照していることを知っていますので、古い値はまだそこにあります。メモリ内のサブセットを減らすには、新しいArrayList(counter.subList)のようなものが必要です。 –

2

この目的でJavaクラスDecayingCounterを作成しました。なぜコメントを

tau = halfLifeInSeconds/Math.log(2.0) 
value *= Math.exp(deltaTimeInNanos * -1E-9/tau) 
関連する問題