Hab es eben mal mit dem Versuchsaufbau von @cmrudolph und ersetzten System.nanoTime() probiert und ja das sieht gut aus, da bekam ich keine negative Differenz beim zurückstellen der Systemzeit während des laufenden Test Programmes.
Genau das war meine Überlegung. Ich habe jetzt aber festgestellt, dass auch bei einem sleep von einer halben Stunde die 10ms so bleiben und sich nicht aufsummieren.
Das Projekt ist halt ein typisches Schulprojekt so nach dem motto ‚macht mal was, fallt auf die schnauze und lernt daraus‘. Es ging darum, einen kleinen Timer zu erstellen, wo du zum beispiel eine stunde einstellen kannst und nach dieser stunde ein fenster aufpoppt. zumindest für die java-frischlinge
für die fortgeschritteneren war dann eben noch das ziel gegeben, die Zeitungenauigkeit auf ein minimum zu reduzieren und das programm gegen fiktive spassvögel abzusichern, die an den einstellungen rumschrauben. es sollte ausserdem ein kleines Fenster mit einer Progressbar auftauchen, wo die schon abgelaufene zeit in prozent angezeigt wird.
hätte ich so eine riesige debatte erwartet, hätte ich auch nicht unter ‚Erste Schritte‘ gepostet, das könnt ihr mir glauben die ursprüngliche frage war ja nur, ob currentTimeMillies() manipulierbar ist
Das ist eine Aussage, mit der man etwas anfangen kann. Es ist also einfach eine Anforderung an die Anwendung.
Da du ja jetzt festgestellt hast, dass Thread.sleep() genau genug zu sein scheint, ist das wohl die beste Lösung.
Wenn du dir dann noch ein vernünftiges Verhalten für die InterruptedException ausdenkst, dann kann man den Timer auch stoppen.
Ok, dann lautet die Antwort, ja ist manipulierbar
Ähm da er ja auch den Fortschrittsbalken anzeigen möchte, würde ich ansonsten noch System.nanoTime() verwenden, da das scheinbar nicht manipulierbar ist.
Ansonsten geht der Thread.sleep() natürlich, da er ja nur eine sehr geringe Abweichung hat (unabhängig von der Dauer)
Was natürlich auch gehen würde, wäre um den Progressbar anzuzeigen, mehrere Thread.sleep() (da ja Prozent ca 100) die durchlaufen werden, jeder läuft dann 1/100 der gesamt Zeit minus der benötigten Zeit für die Grafik-Aktualisierung.
Genau so hab ich das jetzt auch gelöst Zusätzlich berechne ich beim Start der Applikation die ungefähre Abweichung und ziehe die dann von den steps ab
natürlich - alles andere würde das interne des Betriebssystems durcheinander bringen - die 10ms dürften sich auf Scheduling & Co. begründen - also reine Verwaltungszeit
@TheUnregistered meinst du so?
public class timer{
public static void main(String[] args) {
long time=30000;
int steps=100;
long start=System.currentTimeMillis();
for (int i=0; i<steps;i++){
doStep(time/steps, i);
}
System.out.println(System.currentTimeMillis()-start);
}
public static void doStep(long time, int step){
long start =System.currentTimeMillis();
paint(step);
long diff= System.currentTimeMillis()-start;
try {
Thread.sleep(time-diff);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void paint(int step) {
System.out.println(step);
}
}
Vom Benutzer vor- oder zurückgestellte Zeit, nicht zeitzonen-/standortbedingt, bekommst du nicht mit und kannst du auch nicht untersagen.
Du kannst z.B. alle 1000ms prüfen, ob startzeit vor endzeit liegt. Wenn nicht der Fall, addierst du 0 zur Gesamtzeit (sonst Differenz).
Das bringt deine Anwendung aber sofort durcheinander, wenn du eine zweite Java-Anwendung startest, die alle 50ms die Systemzeit auf 17:28 Uhr 0.0 Sekunden stellt.
Wenn du < 1000ms prüfst, bekommst du ein Lag.
Online-Spiele (u. a.) tuen sich auch schwer/schwierig mit diesem Problem.