Mehrere Threadszustände synchronisieren

tuttle64

Bekanntes Mitglied
Hallo allerseits
Ich habe ein solcher Thread, der verschiedene Zustände durchläuft, bis FINISH gesetzt wird.

Code:
public class SynchronThread extends Thread {

	enum State {
		START, STEP1, STEP2, END, FINISH
	}

	public SynchronThread() {
		state = State.START;
	}

	private State state;

	public void run() {

		while (this.state != State.FINISH) {
			switch (state) {
			case START:
				System.out.println("Entering START state");
				System.out.println("Finish START state" );
				state = State.STEP1;
				break;
			case STEP1:
				System.out.println("Entering STEP1 state");
				System.out.println("Finish STEP1 state" );
				state = State.STEP2;
				break;
			case STEP2:
				System.out.println("Entering STEP2 state");
				System.out.println("Finish STEP2 state" );
				state = State.FINISH;
				break;
			default:
				break;
			}
		}
	}

Nun habe ich mehrere solcher Threads und die sollen alle erst enden, wenn alle STEP2 durchlaufen haben. Ist der Ansatz mit Switch-Case schon unglücklich oder kriege ich das noch hin? Falls ja, wie?
 

Bernd Hohmann

Top Contributor
So wie es da steht, macht der Switch/Case keinen Sinn weil am Ende jedes Blocks der nächste State aufgerufen wird - da kannst Du es auch direkt hintereinander schreiben. Was ich auch so recht nicht verstehe: warum dürfen die Threads erst enden, wenn STEP2 durchlaufen wurde? Da hinter diesem Schritt nichts mehr kommt, sehe ich da im Moment keinen Grund dafür.

Was anderes wäre es, wenn sich der Thread schlafen legen soll bis sich der Status ändert. Dazu schau dir mal Object#wait() und Object#notify() an.

bernd
 

tuttle64

Bekanntes Mitglied
So wie es da steht, macht der Switch/Case keinen Sinn weil am Ende jedes Blocks der nächste State aufgerufen wird - da kannst Du es auch direkt hintereinander schreiben. Was ich auch so recht nicht verstehe: warum dürfen die Threads erst enden, wenn STEP2 durchlaufen wurde? Da hinter diesem Schritt nichts mehr kommt, sehe ich da im Moment keinen Grund dafür.

Was anderes wäre es, wenn sich der Thread schlafen legen soll bis sich der Status ändert. Dazu schau dir mal Object#wait() und Object#notify() an.

bernd


Hinter STEP2 kommen noch weitere case Zustände und wait()/notify() darf man in dieser Aufgabe nicht verwenden und die Abläufe in den STEPS müssen in separaten Threads laufen.
 

tuttle64

Bekanntes Mitglied
Aber vielleicht könntest Du die Aufgabe kurz zitieren, das würde helfen.

Stelle Dir vor, eine bestimmte Anzahl Köche (Threads) müssen eine bestimmte, gleiche Anzahl Menus zubereiten. Die Zubereitung kann erst beginnen, wenn alle Köche die Küche betreten haben. Sobald alle Köche Ihr Münu serviert haben, kann mit dem nächsten Durchgang gestartet werden. Der erste Durchgang ist dann beendet und der zweite Durchgang beginnt.

Das Problem liegt darin, eine bestimmte Aufgabe erst dann zu starten, wenn die vorhergehende beendet worden ist. Man könnte jede Aufgabe als Thread implementieren und dann mit Join() wieder zusammenführen. Bei vielen Köchen und Aufgaben scheint mir das wenig praktikabel zu sein.

Ich habe pro Koch einen Thread und darin alle Aufgaben gekapselt, die dann den Ablauf mit Switch-Case gesteuert. Allerdings fällt mir jetzt die synchronisierung schwer.
 
Zuletzt bearbeitet:

Bernd Hohmann

Top Contributor
Vielleicht hilft (wie in einer Großlüche auch) ein "Maître de Cuisine".

In etwa so:

Code:
KochThread koeche[]=new KochThread[upb_chefs];
for (int i=0;i<upb_chefs;i++) {
  koeche[i]=new KochThread();
  koeche[i].start();
}

for (current_state=State.START ... State.END) {

  do {
    int ready=0;
    for (int i=0;i<upb_chefs;i++) {
       if (koeche[i].getState() == current_state) ready++;
    }
  while (ready != upb_chefs);

  for (int i=0;i<upb_chefs;i++) {
     koeche[i].setState(current_state+1);
  }

 } // next state

So in etwa. Bleibt "nur" noch das Problem, wie man ohne notify/wait den Koch-Thread dazu bringt sich nach erreichen des nächsten States schlafen zu legen.

Bernd
 

Bernd Hohmann

Top Contributor
Nach jedem State geht der Thread in eine Endlosschleife, die "wartet", bis alle Threads einen bestimmten Status erreichen.

Das mit der Endlosschleife ist eher eine schlechte Konstruktion, die wird dem Dozenten nicht gefallen.

Klassisch wegprogrammiert würde man statt der Endlosschleife ein .wait() nehmen und beim setzen des States ein .notify() auf das jeweilige Objekt was man als Lock nimmt absetzen damit er aus wait() herausfällt. Ich hatte einen Link mit höher abstrahierten Alternativen gepostet.

Vielleicht will der Aufgabensteller auch auf eine BlockingQueue hinaus: Galileo Computing :: Java ist auch eine Insel – 13.7 Queues (Schlangen) und Deques

Bernd
 

Neue Themen


Oben