# Warten bis alle Threads fertig sind



## Sophie (12. Okt 2011)

Hallo

Ich komme weiss hier leider nicht mehr weiter. Ich habe eine Klasse die Matrizen multipliziert und das Ergebnis dann einfach auf der Konsole ausgeben soll. Das funktioniert alles. Jetzt möchte ich das ganze mit Threads machen. Jetzt gibt es aber Probleme mit der Ausgabe auf der Konsole, da jeder Thread wie er möchte in die pringMatrix() Methode reingeht und irgendwas ausgegeben wird.

Hier erstmal der Code


```
@Override
	public void run() {

		for (int i = 0; i < arrA[0].length; i++) {
			C = new int[arrA.length][arrB[0].length];
			int id = Integer.parseInt(Thread.currentThread().getName());
			System.out.println("\nThread: " + id);
			for (int j = 0; j < arrA[0].length; j++) {
				for (int k = 0; k < arrB[0].length; k++)
					C[i][j] += arrA[i][k] * arrB[k][j];
			}
		}
		printMatrix(C);
		System.exit(0);
	}

	void printMatrix(int[][] c) {

		for (int i = 0; i < c.length; i++) {
			for (int j = 0; j < c[i].length; j++) {
				System.out.print(c[i][j] + " ");
			}
			System.out.println();
		}
	}
```

Ich habe schon mehrere Sachen ausprobiert, funktioniert aber nicht wirklich. Ich denke die Beste Lösung wäre eine while -Schleife, aber ich weiss nicht so ganz was ich dort reinschreiben sollte. Müsste sowas sein wie (wenn C noch nicht komplett gefüllt). Habe auch mit sleep() versucht, funktioniert aber auch nicht.
Kann mir jemand weiterhelfen?


----------



## njans (13. Okt 2011)

Wenn du Thread.join() aufrufst, dann wird so lange gewartet, biss der Thread fertig ist.
Also einfach aus deiner start-methode join() auf jeden Thread aufrufen.
Wenn das nicht reicht, dann müsste man mal schauen, was das concurrency-package als Barrier anbietet


----------



## Michael... (13. Okt 2011)

Was hast Du mit den Threads vor und was erwartest Du Dir davon? Sollen die etwa alle in der selben Matrizze rumrechnen?
Was soll das System.exit(0) in der run-Methode?


----------



## Sophie (13. Okt 2011)

hm, ja mit join() habe ich auch versucht, aber dann macht ja der erste thread der reinkommt alles und die restlichen sind überflüssig. oder verstehe ich da etwas falsch?


----------



## Sophie (13. Okt 2011)

Michael... hat gesagt.:


> Was hast Du mit den Threads vor und was erwartest Du Dir davon? Sollen die etwa alle in der selben Matrizze rumrechnen?
> Was soll das System.exit(0) in der run-Methode?



Ja, alle Threads sollen zwei Matrizen multiplizieren. Je Zeile ein Thread. Das System.exit() kommt sofort weg, hat dort nix zu suchen


----------



## njans (13. Okt 2011)

Nun ich nehme mal an, du startest ja die Threads ungefähr so:

```
for (...)
new Thread(parameter);
```

Da kannst du ja die Threads in einem Array speichern:

```
Thread[] myThreads;
for (...)
myThreads[..]  = new Thread(parameter);
```

Und dann kannst du alle auf jeden Thread im Array join() aufrufen.


----------



## Michael... (13. Okt 2011)

Aber das was du in der run() machst macht doch nicht viel Sinn. Die äußer for Schleife wiederholt A[0].length mal das selbe?? Und verwirft x mal das neu erstellte und befüllte C.
Wenn Du jede Ergebniszeile in einem eigenen Thread errechnen lassen willst benötigst Du ja A.length Threads. Jeder Thread muss ein int[] der Länge B[0].length berechnen. (wenn man die erste "Dimension" als Zeilenindex und die zweite "Dimension" als Spaltenindex interpretiert)
Sobald ein Thread fertig ist fügt er entsprechend seines "Zeilenindexes" das ermittelte int[] an die passende Stelle von C ein und erhöht z.B. synchronisiert einen Zähler und informiert z.B. einen Beobachter, der sobald der Zähler, der Anzahl der Threads also A.length entspricht somit weiss, dass die Berechnung abgeschlossen ist und C ausgegeben werden kann.


----------



## Sophie (13. Okt 2011)

Wenn ich join() einsetze, dann sieht die Ausgabe schon mal besser aus. Das Problem ist aber, das jeder Thread einmal über die Methode geht und ausgibt.  Es sollte aber nur einmal sein. Ist es irgendwie möglich, dass zum Beispiel nur der erste oder der letzte Thread der dort ankommt ausgibt?

Michael, tut mir Leid, Du hast Recht. Ich hänge schon ziemlich lange an diesem Code und hab den wohl zwischendurch mal geändert. Richtig sollte es so aussehen


```
for (int i = 0; i < arrA.length; i++) {
			for (int j = 0; j < arrB[0].length; j++) {
				for (int k = 0; k < arrA[0].length; k++) {
					C[i][j] += arrA[i][k] * arrB[k][j];				
				}
			}
		}
```


----------



## Spacerat (13. Okt 2011)

1. Mit [c]join()[/c] hintereinander auf jeden Thread erlebt man so manche Überraschung bzw. Exceptions oder Deadlocks - z.B. wenn ein Thread schon beendet wurde bevor [c]join()[/c] aufgerufen wird.
2. Es gibt da das paket java.util.cocurrent, damit sollte es gehen.
3. Da gibt es noch die Klasse [c]Threadgroup[/c] und in dieser eine [c]interrupt()[/c]-Methode für alle Threads innerhalb dieser Gruppe sowie eine [c]activeCount()[/c]-Methode - (recommended for informational purposes only!), die 0 zurück gibt, wenn der letzte Thread der Gruppe beendet wurde.


----------



## Sophie (13. Okt 2011)

Hallo Spacerat

Ich weiss nicht so ganz, wie Du meinst, dass man diese ThreadGroup verwenden könnte.
Ich muss ja vorher festlegen welche Threads in diese Group kommen und ich weiss ja noch nicht, welcher Thread als letztes aus der for-Schleife rausgeht. Einen Thread brauche ich ja noch um mir die Matrix ausgeben zu lassen.


----------



## hdi (13. Okt 2011)

> Das Problem ist aber, das jeder Thread einmal über die Methode geht und ausgibt. Es sollte aber nur einmal sein. Ist es irgendwie möglich, dass zum Beispiel nur der erste oder der letzte Thread der dort ankommt ausgibt?



Ja das ist möglich, und du brauchst auch keine ThreadGroup o.ä. dafür. Lass deinen Code so wie ursprünglich gepostet und leg einfach eine (natürlich statische!) Zählvariable in deiner Klasse an, die jeder Thread am Ende seiner run-Methode inkrementiert. Das printMatrix() dann in ein entsprechendes if-Statement hinter das Inkrement packen. Du kannst dir dann aussuchen ob das der erste, der letzte, oder sonst irgendein Thread tun soll. 

*Achtung:* Der Zugriff  auf die Zählvariable muss jeweils synchronisiert sein, sonst drohen Race Conditions (genauer: Lost Updates, was dazu führen kann dass am Ende gar nix ausgegeben wird). Wenn du's nicht hinkriegst sag Bescheid. Sind nur 4 Zeilen...


----------



## Michael... (13. Okt 2011)

Sophie hat gesagt.:


> Richtig sollte es so aussehen
> 
> ```
> for (int i = 0; i < arrA.length; i++) {
> ...


So würde man vorgehen, um die Ergebnismatrix komplett in einem Thread zu berechnen. Jetzt musst Du nur noch die Berechnung der einzelnen Zeilen (die werden ja mit den inneren zwei Schleifen berechnet) herauslösen und auf verschiedene Threads verteilen...


----------



## Spacerat (13. Okt 2011)

Also die resultierende Matrix ist ja wie es scheint in jedem Thread die selbe. Von daher würde ich dieses [c]printMatrix()[/c] schon mal von ausserhalb der Thread-Run-Methode aufrufen und zwar erst dann, wenn alle Threads mit ihren Berechnungen fertig sind. Deswegen dachte ich da an ThreadGroup - Thread instanzieren, der Gruppe hinzufügen, Thread starten, auf [c]activeCount() == 0[/c] warten und von ausserhalb [c]printMatrix()[/c] aufrufen. Diese [c]activeCount()[/c]-Methode ist prinzipell das, was hdi dir mit dieser Zählvariable vorgeschlagen hat aber eigentlich halt nur für rein informative Lösungen - so steht's in der API.
Das Ganze geht aber auch immer noch mit [c]java.util.concurrent[/c] viel sauberer und einfacher.


----------

