Warum ist Timer schneller als While?

ruerob

Mitglied
Ich begrüße euch mit einem freundlichen Hallo.

Ich stehe vor folgendem Rätsel:

Wenn ich eine Methode sehr oft hintereinander ausführen möchte und das über eine While-Schleife tue, habe ich weniger Schleifendurchläufe pro Sekunde, als wenn ich das gleiche über einen Timer.scheduleAtFixedRate(new Timertask(),3,3); tue.

Warum ist das so? Ich schreibe mal die zwei Varianten auf:

Hier nun zuerst die langsamere Variante
Java:
public void init(){
  Timer timer = new Timer();
  timer.schedule(new TimerTask(){public void run(){loop();}}, 3);
}

public void loop(){
  while(true)
    run();
}

und jetzt die schnellere Variante
Java:
public void init(){
  Timer timer = new Timer();
  timer.scheduleAtFixedRate(new TimerTask() { public void run() {loop();}},3,3);
}

public void loop(){
    run();
}

Ich hab es mit der neusten Java VM probiert.
Meine Entwicklungsumgebung ist Eclipse,
und als Betriebssystem nutze ich Windows XP Home SP2.
 
Danke für die schnelle Antwort.

Nein in meinem Rechner hab ich nur ne CPU mit einem Kern.
Nämlich den AMD Athlon 64 3800+ mit 2.39 GHz.
Ich habs auch auf einem Netbook mit Intel Atom Prozessor getestet, war aber genau das gleiche.

Ich starte in der Schleife ein repaint. Wenn ich das mit der Whileschleife tue, komme ich auf maximal 160 Bilder pro Sekunde, wenn ich nur die Bilderzahl ausrechnen und anzeigen lasse. Mit dem Timer erreiche ich allerdings maximal 289 Bilder pro Sekunde.

Da der Unterschied so groß ist, frage ich mich da, was macht der Timer so anders?

EDIT: Selbst wenn ich die Methode loop() als synchronized kennzeichne komme ich mit dem Timer auf die höheren Werte.
 
Zuletzt bearbeitet:
Wiedermal danke für die schnelle Antwort.

Wenn ich
Java:
timer.scheduleAtFixedRate(new TimerTask() { public void run() {loop();}},3,3);

in

Java:
timer.schedule(new TimerTask(){public void run(){loop();}},3,3);

änder, bekomme ich konstante 65 Bilder pro Sekunde angezeigt.

Selbst wenn ich noch "ein paar Berechnungen" pro Bild hinzufüge, bleibt er bei diesem Wert.
Nutze ich scheduleAtFixedRate habe ich 289 Bilder pro Sekunde. Wenn ich da einen Softwarerenderer mit in der Schleife laufen lasse, habe ich nur noch 160 Bilder.
Wenn ich aber schedule benutze, bleibt der Wert mit und ohne Renderer bei 65 Bildern pro Sekunde.

Alles seltsam...
 
Zuletzt bearbeitet:
Morgäääähn,

das "schedule()" eher "konstant" läuft im Vergleich zu scheduleAtFixedRate() ist mit ein paar Sätzen hier: Timer (Java Platform SE 6) erklärt.

Die Differenz zwischen while und dem Thread kann ich dir nicht erklären, dazu fehlt einfach der ganze Code. Aber auch auf Einkern-Prozessoren kann es etwas bringen Multithreading zu verwenden, das Betriebssystem hat ja diverse Möglichkeiten zur Verwaltung und Ausführung etc. pp. Kann gut sein das es einfach daran liegt. 🙂
 
Galileo Computing :: Java ist auch eine Insel – 14.7 Zeitgesteuerte Abläufe

Die schedule()-Methode gibt es in vier Ausführungen. Dazu kommen zwei Methoden scheduleAtFixedRate(), die versuchen, die Genauigkeit zu verbessern. Dies lohnt sich bei Operationen, die über einen langen Zeitraum präziser ohne Drift ausgeführt werden sollen, wie es etwa bei einer Uhr gilt, die jede Stunde ihren großen Zeiger bewegt. Selbst wenn Hintergrundoperationen, wie Garbage-Collection, die pünktliche Ausführung der Operation verhindern, wird die Verspätung bis zur nächsten Wiederholung aufgeholt.
 
Also bei mir schafft die "schnellere Variante" wesentlich weniger. Das liegt daran, das sie die run() Methode (nicht die anonyme!) wesentlich weniger aufruft als die "langsamere" Variante, die durch "while(true) run();" ja ein Dauerfeuer produziert. Bei mir schaffe ich mit der "schelleren" Variante gerade mal 1000 Aufrufe in einer Sekunde, während die andere Variante 100000000 in einer Sekunde macht.
Ich denke der Geschwindigkeitsunterschied kommt daher, das die run()-Methode sehr rechenintensiv ist und ein "Dauerfeuer" an dieser Stelle eher schadhaft ist, als sozusagen "kontrollierte" Aufrufe.
 
Zuletzt bearbeitet:
Nochmal einfacher:

in der ersten Variante wird alle drei Sekunden ein wahres Dauerfeuer fabriziert (while(true) run()😉, in der zweiten wird alle drei Sekunden einmal run() aufgerufen.
 
Das mit dem "Dauerfeuer" war die Lösung. Wenn ich in die Whileschleife ein Thread.sleep(1) einbaue bekomme ich einen Maximalwert von 520 Bildern pro Sekunde. Allerdings bekomme ich mit zugeschaltetem Softwarerenderer jetzt maximal nur noch 120 Bilder in der Sekunde.

So sieht die neue Variante aus:
Java:
public void loop() {
	while(true){
		repaint();
		try {
			Thread.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

EDIT: Das ich nur noch 120 Bilder pro Sekunde bekomme, liegt dann wohl aber an der Milisekunde, die der Thread nach jedem Schleifendurchlauf wartet.

Dann ist ja alles geklärt.

Vielen Dank an alle die mir hier geholfen haben.

Ruerob
 
Zuletzt bearbeitet:

Zurück
Oben