Schleife mit leerem Anweisungsblock wird trotz erfüllter Bedingung nicht verlassen

chaostheory

Bekanntes Mitglied
Hallo,
ich schreibe gerade ein 2D-Spiel, bei dem zunächst nur ein leerer Bildschirm angezeigt wird und der user aufgefordert wird, die Enter-Taste zu drücken. Während mein KeyListener also schön wartet, lasse ich die Hauptklasse mit dieser Methode warten:
Java:
while(!running){}
Wenn dann allerdings Enter gedrückt wird, wird die Schleife nicht verlassen, obwohl die Variable korrekt auf true gestellt wurde. Schreibe ich irgendeine Anweisung in den Block funktioniert es.
Ist es nicht möglich die Schleife leer zu lassen?
 
das problem ist das auf grund des leeren loop-body die schleife so unheimlich schnell läuft *und auch extrem den cpu belastet* das das system einfach nicht mehr zum checken der bedingung kommt ...
baue einfach mal ein [c]Thread.sleep(100);[/c] ein ... das sollte das problem lösen ... nebenbei dürfte deine cpu-last auch deutlich nach unten sinken ...
 
Mir erschließt der Sinn deiner Dauerschleife nicht.
Wenn der User Enter drückt kannst du doch explizit ne Methode anstoßen.
 
Wenn man 'running' als
private volatile boolean running = ...
deklariert, geht es zwar, aber es ist trotzdem noch Unfug. Da gehört mindestens ein 'Thread.sleep(...)' rein, vermutlich sogar eher ein wait() und an anderer Stelle das passende notifyAll()...
 
Mir erschließt der Sinn deiner Dauerschleife nicht.
Wenn der User Enter drückt kannst du doch explizit ne Methode anstoßen.

Ja, stimmt auch. Allerdings würde so bei jedem Enter ein neues Spiel gestartet, es sei denn ich benutze wieder eine boolesche Variable.

Vor allem aber stammt der Code aus meiner main-Methode und würde ich die nicht bis zum Ende laufen lassen, wäre das Programm doch sofort vorbei!?
 
Wenn ich den Thread in der Schleife jedes Mal 100 Millisekunden warten lasse, funktioniert es wunderbar. Notify wäre hier nicht so gut, weil mein KeyListener ja keine Berechtigung hat die Main-Klasse aufzuwecken.

Hier noch mal etwas mehr Code, aber falls es nichts Besseres als wait() gibt hat es sich erledigt, denn das klappt auch gut.

KeyHandler:
Java:
public void keyPressed(KeyEvent event) {
		int keyCode = event.getKeyCode();
		
		switch(keyCode) {		
			case KeyEvent.VK_ESCAPE :	main.setRunning(false);												break;
			case KeyEvent.VK_RIGHT :	main.getPlayerList().get(0).setDirection(Player.Direction.RIGHT);	break;
			case KeyEvent.VK_LEFT :		main.getPlayerList().get(0).setDirection(Player.Direction.LEFT);	break;
			case KeyEvent.VK_ENTER :	main.setRunning(true);												break;
		}
		
		event.consume();
	}

Und dann die Methode run(), die von der main-Methode aufgerufen wird und bisher das ganze Spiel durchläfut:

Java:
//Main method called from main
	public void run() {	
		init();

		printStart();
		
		//Do nothing until game starts
		while(!running){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {}
		}
		
		try{
			movieLoop();
		}finally{
			screenManager.restoreScreen();
		}
	}
 
init() und printStart() haben da mMn nicht drin verloren. Die solltest du woanders parken.

In deinem EventListener startest du dann einfach den Thread und es kann losgehen.
 
Java:
        while(!running){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {}
        }

Dieser Anstatz ist nicht grad das gelbe vom Ei. So kann es jetzt beim Starten des Spiels zu einer Verzögerung bis 100ms kommen. Aber den sleep-Wert runterdrehen ist auch keine Lösung, denn je kleiner der wird, desto mehr bewegst du dich in Richtung "busy waiting" - auch schlecht.

Wie schon gesagt wurde solltest du über wait() und notify() gehen. Stichwort Synchronisation. Damit musst du dich eh beschäftigen, da dein Code buggy ist. Sofern running nämlich nicht als volatile deklariert wurde kann es sein dass du ewig in dieser Schleife hängst - auch nachdem running auf true gesetzt wurde! Der Fall tritt u.U. so gut wie nie ein, kommt drauf an was du sonst so für Anweisungen in deinem Code hast. Aber theoretisch kann es sein dass dein Spiel NIE startet.
 

Zurück
Oben