2016-07-07 5 views
2

Ich brauche einen Zähler, der erhöht wird, wenn bestimmte Aufgaben abgeschlossen sind. Wir brauchen den Wert für nur letzte Stunde, dh das Fenster wird sich bewegen und nicht für statische Stunden.Java-Zähler mit Wert für die letzte Stunde

Was ist der beste Weg, um darüber zu gehen? Eine Möglichkeit, an die ich denken konnte, war ein Array der Größe 60, eins für jede Minute und den Eintrag für die jeweilige Minute zu aktualisieren und insgesamt auf einem get() zu machen. Beim Wechsel zu einer neuen Minute wird das Array zurückgesetzt.

Gibt es bessere Lösungen? Irgendwelche zeitbasierten Implementierungen von Counter verfügbar?

+2

downvoter, Pflege, warum zu kommentieren? – rajesh

+0

Erstellen Sie einen "AtomicInteger" -Zähler und einen Timer-Dienst. Zähler erhöhen, wenn die Aufgabe abgeschlossen ist. Wenn Sie den Timer-Dienst verwenden, setzen Sie den Zähler nach jeder Stunde auf Null zurück. Wenn Sie alte Daten speichern möchten, setzen Sie vor dem Zurücksetzen des Zählers '' in eine Karte. – sauumum

+0

warum Sie es im Maßstab jeder Minute zählen, warum nicht einfach eine einzelne (vielleicht lange) Ganzzahl verwenden? – Tiina

Antwort

2

Sie können eine Art Array implementieren, das Ihnen die besten Werte liefert (und zum Zeichnen von Diagrammen usw. verwendet werden kann). Aber wenn Sie daran interessiert sind, es in Einzelwert zu tun, gibt es einen Trick, um richtige Annäherung zu bekommen. Es wird zum Beispiel in loadavg Berechnung auf Unix https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation

Systeme berechnen die durchschnittliche Belastung als exponentiell gedämpft/gewichteten gleitenden Durchschnitt der Last Nummer verwendet. Die drei Werte des Lastdurchschnitts beziehen sich auf die vergangenen ein, fünf und fünfzehn Minuten des Systembetriebs. [2]

Mathematisch ausgedrückt, bilden alle drei Werte immer die gesamte Systemlast ab, seit das System gestartet wurde. Sie zerfallen alle exponentiell, aber sie zerfallen mit unterschiedlicher Geschwindigkeit: sie nehmen nach 1, 5 und 15 Minuten exponentiell ab. Daher wird der 1-Minuten-Lastdurchschnitt 63% (genauer: 1 - 1/e) der Last von der letzten Minute plus 37% (1/e) der Last seit dem Start ohne die letzte Minute addieren. Für den Lastdurchschnitt von 5 und 15 Minuten wird das gleiche 63%/37% -Verhältnis über 5 Minuten bzw. 15 Minuten berechnet. Daher ist es technisch nicht korrekt, dass der 1-Minuten-Lastdurchschnitt nur die letzten 60 Sekunden Aktivität umfasst (da er immer noch 37% Aktivität aus der Vergangenheit enthält), aber das beinhaltet meistens die letzte Minute.

Computing auf Einzelwert gleitenden Durchschnitt - es gibt mehrere Möglichkeiten, im Detail beschrieben, mit einigen Beweise hier https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average

beste für Ihren Anwendungsfall ist dies wahrscheinlich ein https://en.wikipedia.org/wiki/Moving_average#Application_to_measuring_computer_performance

equation

+0

Lassen Sie mich das überprüfen, danke. – rajesh

1

Für einfachere Technik, aber nette Lektüre von Artur!

Sie könnten einfach eine Liste verwenden, um jede benötigte Zeit zu speichern. Dann filtern Sie diese, wenn Sie die Liste erhalten.

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

Das Ergebnis wird eine Liste (sortierte, da die Add-Methode nur current hinzufügen), ohne älteren Wert. Dies ist eine grundlegende Implementierung, bessere Techniken könnten aber für eine schnelle Lösung verwendet werden. Dies könnte es tun.

Der Filter ist auf dem Getter gemacht. Dies bedeutet, dass die Liste in der Länge explodieren könnte, wenn dieses Lesen nur selten erfolgt. Also könnte dies auch in der add-Methode gemacht werden.

+0

Das Entfernen alter Werte wäre wahrscheinlich gut, sonst kann die Liste für immer wachsen. –

+0

Dies geschieht über die SubList, ich setcounter vor der Rückgabe;) aber ich habe nur einen Absatz darüber. – AxelH

+0

Sie wissen, dass die Unterliste auf das ursprüngliche Array verweist, also sind alte Werte immer noch da, nur durch diesen Zeiger nicht zugänglich? Du brauchst etwas wie eine neue ArrayList (counterslist), um eine reduzierte Teilmenge im Speicher zu erhalten. –

2

Ich habe die Java-Klasse DecayingCounter für diesen Zweck geschrieben.

Es verwendet die folgenden Formeln eine exponentiell Zeit abklingende Zähler zu implementieren:

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