# Thread.sleep() ungenau???



## pocketom (23. Jun 2009)

Das ist wohl eine Problem für die Profis hier:

Gerade ist mir aufgefallen dass _Thread.sleep(1);_ nicht das geünschte Ergebnis liefert, statt 1 ms wartet der Thread ca. 30ms, bei mehrmaliger Ausführung hintereinander nähert man sich dann im Schnitt langsam an. Auch _sleep(0,1)_ unter Zuhilfename der Nanosekunden schafft da keine Abhilfe, weswegen sich mir im Moment grad nicht erschliesst wieso ich Nanosekunden hier überhaupt einsetzen kann?

*Folgendes Beispiel verdeutlicht es:*

```
public class Test {

	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {

		long millis = 100;
		
		
		long start = System.currentTimeMillis();
		for(int i=0;i<millis; i++)
		{
			Thread.sleep(1);
		}
		long end = System.currentTimeMillis();	
		
		System.out.println("TIME: "+(end-start));
	}
}
```

Was tun wenn ich also nur eine kurze und möglichst exakte Wartezeit von ~1-2 ms haben will?


----------



## Wildcard (23. Jun 2009)

pocketom hat gesagt.:


> Was tun wenn ich also nur eine kurze und möglichst exakte Wartezeit von ~1-2 ms haben will?


Geht so nicht, dafür löst der Scheduler des Betriebssystems das nicht genau genug auf.
Kurz Warten geht mit yield, lang warten geht mit sleep. Dazwischen gibt's nur busy waiting, oder die Kombination aus busy waiting und sleep wenn es nichts ausmacht das ein yield auch mal länger dauern kann als 1ms. Warum willst du überhaupt so kurz Schlafen und das auch noch exakt?


----------



## pocketom (23. Jun 2009)

Ich arbeite gerade mit *iText* an der automatischen Erstellung von PDF Dokumenten. Leider läuft da irgendetwas nicht synchron, ich erstelle in einer Schleife einen Funktionsgraphen und füge danach eine neue Seite ein. Leider habe ich auf vielen Seiten dieselbe Abbildung obwohl jedesmal etwas anderes zu sehen sein sollte. Füge ich in die Schleife ein sleep(1) ein gehts, aber bremst auch (zu) stark... Wäre natürlich schöner das Problem an der Wurzel anzupacken, aber ich habe einfach keine Ahnung was da schief läuft...


----------



## Wildcard (23. Jun 2009)

Nun, du wirst nicht unhinkommen das Problem doch an der Wurzel anzupacken, denn sonst kommst du von 'funktioniert meistens nicht' zu 'funktioniert beim Kunden nicht mehr' und das ist eigentlich schlimmer als vorher (ohne das sleep)


----------



## Schandro (23. Jun 2009)

> Auch sleep(0,1) unter Zuhilfename der Nanosekunden schafft da keine Abhilfe, weswegen sich mir im Moment grad nicht erschliesst wieso ich Nanosekunden hier überhaupt einsetzen kann?


Hier mal der Code von sleep mit nanosekunden, ich denke das sagt alles...

```
public static void sleep(long millis, int nanos) 
    throws InterruptedException {
	if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
	}

	if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
				"nanosecond timeout value out of range");
	}

	if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
	    millis++;
	}

	sleep(millis);
    }
```
Aber wie bereits gesagt wurde läuft sleep eh im Millisekundenbereich ungenau.


----------



## pocketom (24. Jun 2009)

OMG!!! Da muss man sich echt fragen was Nanosekunden überhaupt in Java verloren haben...


----------



## maki (24. Jun 2009)

pocketom hat gesagt.:


> OMG!!! Da muss man sich echt fragen was Nanosekunden überhaupt in Java verloren haben...


Nanosekunden sind eine Masseinheit, sonst nix 
Aber vielleciht brauchst du ein RTOS..


----------



## pocketom (24. Jun 2009)

Naja, ich habe zum Glück mittlerweile die Ursache finden können, ein falsch initialisierter Randomizer war schuld.... Ich habe den nun in die Schleife hineingepackt und seede mit Zeit+Schleifenindex. Kaum macht mans richtig schon gehts auch


----------



## Wildcard (24. Jun 2009)

pocketom hat gesagt.:


> Naja, ich habe zum Glück mittlerweile die Ursache finden können, ein falsch initialisierter Randomizer war schuld.... Ich habe den nun in die Schleife hineingepackt und seede mit Zeit+Schleifenindex. Kaum macht mans richtig schon gehts auch



Und ist das nicht auch viel besser als sinnlos zu schlafen?


----------



## Saxony (25. Jun 2009)

Hiho,

Stichworte in diesem Zusammenhang sind:

- Zeitscheibe
- Präemptives Multitasking

Für WinNT beispielsweise waren es 10ms - also jeder Thread.sleep(0..10) Aufruf dauert also mind. 10ms unter WinNT.

Das Einzige was in einem Rechner wirklich in ns gemessen wird und auch so arbeitet sind die Schaltzeiten von Arbeitsspeicher.

bye Saxony


----------



## Saxony (25. Jun 2009)

Schandro hat gesagt.:


> ```
> if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
> millis++;
> }
> ...



LoL - schon tricky die Java Entwickler! Bei denen sind also schon 500k ns eine ms wert. Im Umkehrschluss allerdings ist ein Wert von 499.999 ns nicht beachtenswert ausser die ms sind 0 dann wird selbst eine ns schon zu einer ms. :toll:

Naja was wollen se sonst machen - selbst 1ms ist viel zu fix für den OS Scheduler.


----------

