# Thread Reihenfolge



## The_S (26. Sep 2008)

Hi-Ho!

Sorry für den komischen Titel, mir ist aber nichts besseres eingefallen  .

Folgender Code:


```
public class Test {
	
	public static void main(String[] args) {

		for (int i = 0; i < 100; i++) {
			new Thread(new Runnable() {
				public void run() {
					printSynchronized("Thread 1");
				}
			}).start();
			new Thread(new Runnable() {
				public void run() {
					printSynchronized("Thread 2");
				}
			}).start();
		}
	}
	
	public static synchronized void printSynchronized(String print) {
		System.out.println("Print synchronized Start: " + print);
		try {
			Thread.sleep(50);
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("Print synchronized End: " + print);
	}
}
```

Warum kommt es manchmal vor, dass ich nicht eine Ausgabe in der Form



> Print synchronized Start: Thread 1
> Print synchronized End: Thread 1
> Print synchronized Start: Thread 2
> Print synchronized End: Thread 2
> ...



habe, sondern manchmal so:



> Print synchronized Start: Thread 1
> Print synchronized End: Thread 1
> Print synchronized Start: Thread 1
> Print synchronized End: Thread 1
> ...



oder so:



> Print synchronized Start: Thread 1
> Print synchronized End: Thread 1
> Print synchronized Start: Thread 1
> Print synchronized End: Thread 1
> ...



?

Danke!


----------



## SlaterB (26. Sep 2008)

die Threads sind alle voneinander unabhängig,
es kann sein, dass die main in ihren 5 ms Zeitrahmen 12 Threads startet,
dann erst wird angefangen, auch mal diese auszuführen, und zwar in beliebiger Reihenfolge,

wie weit der Zufall geht mag ich nicht abschätzen,
wenn bei dir immer die 1 zuerst drankommt, dann ist das schonmal nicht völlig zufällig,

zudem müssen die Threads beim synchronized-Block alle warten,
auch dort ist keine Reihenfolge festgelegt, wer als nächster dran ist, auch wenn es anscheinend weitgehend die Reihenfolge des Ankommens ist

bei mir ist es fast immer die erste geordnete Ausgabe, also nicht so schlimm wie ich es soeben aufgemalt habe,
dennoch darf man da gar nichts voraussetzen

hier noch eine kleine Änderung:


```
public class Test
{

    public static void main(String[] args)
    {

        for (int i = 0; i < 10; i++)
        {
            final int ii = i;
            new Thread(new Runnable()
                {
                    public void run()
                    {
                        printSynchronized("Thread 1 "+ii);
                    }
                }).start();
            new Thread(new Runnable()
                {
                    public void run()
                    {
                        printSynchronized("Thread 2 "+ii);
                    }
                }).start();
        }
        System.out.println("fertig");
    }

    public static synchronized void printSynchronized(String print)
    {
        System.out.println("Print synchronized Start: " + print);
        try
        {
            Thread.sleep(50);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        System.out.println("Print synchronized End  : " + print);
    }


}

Ausgabe:

Print synchronized Start: Thread 1 0
fertig
Print synchronized End  : Thread 1 0
Print synchronized Start: Thread 2 0
Print synchronized End  : Thread 2 0
Print synchronized Start: Thread 1 1
Print synchronized End  : Thread 1 1
Print synchronized Start: Thread 2 1
Print synchronized End  : Thread 2 1
Print synchronized Start: Thread 1 2
Print synchronized End  : Thread 1 2
Print synchronized Start: Thread 2 2
Print synchronized End  : Thread 2 2
Print synchronized Start: Thread 1 3
Print synchronized End  : Thread 1 3
Print synchronized Start: Thread 2 3
Print synchronized End  : Thread 2 3
Print synchronized Start: Thread 1 4
Print synchronized End  : Thread 1 4
Print synchronized Start: Thread 2 4
Print synchronized End  : Thread 2 4
Print synchronized Start: Thread 1 5
Print synchronized End  : Thread 1 5
Print synchronized Start: Thread 2 5
Print synchronized End  : Thread 2 5
Print synchronized Start: Thread 1 6
Print synchronized End  : Thread 1 6
Print synchronized Start: Thread 1 7
Print synchronized End  : Thread 1 7
Print synchronized Start: Thread 2 7
Print synchronized End  : Thread 2 7
Print synchronized Start: Thread 1 8
Print synchronized End  : Thread 1 8
Print synchronized Start: Thread 2 8
Print synchronized End  : Thread 2 8
Print synchronized Start: Thread 1 9
Print synchronized End  : Thread 1 9
Print synchronized Start: Thread 2 9
Print synchronized End  : Thread 2 9
Print synchronized Start: Thread 2 6
Print synchronized End  : Thread 2 6
```


edit: also mindestens beim synchronized bin ich mir um der Zufälligkeit recht sicher,
ob die Threads in irgendeiner Reihenfolge im System angemeldet und dann in Reihenfolge oder zufällig gestartet werden/ vor dem Ausführen von printSynchronized() bereits unterbrochen werden, liegt eher im Bereich der Vermutungen


----------



## The_S (26. Sep 2008)

SlaterB hat gesagt.:
			
		

> es kann sein, dass die main in ihren 5 ms Zeitrahmen 12 Threads startet,
> dann erst wird angefangen, auch mal diese auszuführen, und zwar in beliebiger Reihenfolge,



Diese Vorgehensweise hätte ich gerne mal genauer erläutert  . Danke!


----------



## SlaterB (26. Sep 2008)

siehe mein edit am Ende des ersten Postings,
erläutern muss es dir ansonsten wer anders


----------



## Marco13 (26. Sep 2008)

Welcher Thread welche Rechenzeiten bekommt, ist AFAIK Sache der JVM (oder ggf. des Betriebssystems).

Es kann ja sein, dass der erste Thread gestartet wird und schon "mehr als ein mal" durchgelaufen ist, bevor der zweite startet .... d.h. die Zeiten (beginnend bei 0) in denen die Threads in der print-Methode sind, könnten ja (sinngemäß, zur Verdeutlichung) so sein

*T1* : 0 - 50
*T1* : 50 - 100
T2 : 51 -> wird geblockt bis 100, wenn T1 fertig ist 
*T2* : 100 - 150
T1 : 100 -> wird geblockt, bis T2 fertig ist 
*T1* : 150 - 200
T2 : 150 -> wird geblockt, bis T1 fertig ist 
*T2* : 200 - 250
(T1 : Sollte jetzt eigentlich von 250-300 arbeiten, aber da war ein Festplattenzugriff, der ihn auf 252 vertröstet hat)
*T2* : 251 -> 301
T1 : 252 -> wird geblockt, bis T2 fertig ist 
*T2* : 301 - 350

(naja.... "Verdeutlichung"??? Wie auch immer).

es gibt ja erstmal keinen Mechanismus, um das zu verhindern, bzw. die abwechselnde Reihenfolge zu erzwingen...


----------



## The_S (26. Sep 2008)

Ich will das auch gar nicht verhindern, ich hab nur beim erstellen eines neuen Kapitels für mein Java-Blog-Buch dieses Verhalten bemerkt. Mich interessiert einfach nur, von wem/was/unter welchen Voraussetzungen bestimmt wird, in welcher Reihenfolge Threads ausgeführt werden. Und ob das evtl. auch auftreten kann, wenn zwei Threads mit einem "relativ" großem Zeitunterschied gestartet werden.

Dreht sich hier also nicht um das Finden einer Lösung, sondern um die Theorie hinter dieser "Technik"  .

Schonmal danke an euch beide, für jeden weiteren Beitrag bin ich dankbar  .


----------



## EgonOlsen (26. Sep 2008)

Jede Annahme über Reihenfolge oder Zeitaufteilung von Threads ist spekulativ und hängt von VM und OS ab (und ggf. auch CPU). Das einzige, was man verlässlich sagen kann, ist das man es nicht sagen kann. Und so sollte man Threads auch verwenden. Alles andere landet spätestens bei einem OS-Wechsel in der Sackgasse.


----------



## The_S (26. Sep 2008)

OK, kann mir jemand ein Beispiel der Verwaltung für ein beliebiges OS mit einer beliebigen VM nennen? Danke!


----------



## Landei (26. Sep 2008)

Wenn du die Verwaltung nicht selber machen willst, schau dir mal an, was Java so an high-level - Konstrukten so bietet: ExecutorService, Future, PriorityQueues...
Ohne mehr Infos, was du eigentlich vorhast, wird kaum jemand etwas konkretes vorschlagen können


----------



## The_S (26. Sep 2008)

Hobbit_Im_Blutrausch hat gesagt.:
			
		

> Ich will das auch gar nicht verhindern, ich hab nur beim erstellen eines neuen Kapitels für mein Java-Blog-Buch dieses Verhalten bemerkt. Mich interessiert einfach nur, von wem/was/unter welchen Voraussetzungen bestimmt wird, in welcher Reihenfolge Threads ausgeführt werden. Und ob das evtl. auch auftreten kann, wenn zwei Threads mit einem "relativ" großem Zeitunterschied gestartet werden.
> 
> Dreht sich hier also nicht um das Finden einer Lösung, sondern um die Theorie hinter dieser "Technik"  .


----------



## Landei (26. Sep 2008)

OK, wer lesen kann, ist klar im Vorteil. Aber die Theorie hinter der Technik ist eben, dass die Threads in irgendeiner Reihenfolge abgearbeitet werden, d.h., dass die Steuerung nicht über den Startzeitpunkt, sondern innerhalb der Threads selber erfolgen muss.
Wenn man die Threads selber steuern will, lässt man diese oft in einer Schleife arbeiten, in der abgeprüft wird, ob "Arbeit anliegt", und ansonsten den Thread für ein paar Millisekunden schlafen legt. Klassisches Beispiel dafür ist eine Producer/Consumer-Kopplung über eine Queue.


----------



## The_S (26. Sep 2008)

Joa, so bzw. so ähnlich hat das EgonOlsen ja schon beschrieben, jetzt bin ich auf der Suche nach einem Konkreten Beispiel (siehe 4 Posts weiter oben  ). 

Aber danke für deine Hilfe!


----------

