Ergebnis 1 bis 12 von 12

Thema: Java - Einen Moment warten

Baum-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #9
    @Cloud:

    Dein Problem ist, dass du nicht vollkommen verstehst, was du machst und scheinbar auch keine Lust hast, es zu verstehen und stumpf Code abschreibst, der dir vorgegeben wird.

    Code (Java):
     
    else if(GameMode==1) 
    {
        waitingStartTime = System.currentTimeMillis();
        playSound();  
        zeichneSchwarz(g);
     
        if(System.currentTimeMillis() >= waitingStartTime + 500)
        {	
            stopSound();
            GameMode=2;
        }
    }
     


    Was genau passiert hier?
    Die erste Zeile im Block sichert die aktuellen Millisekunden.
    In den nächsten zwei Zeilen spielst du einen Sound ab und zeichnest dein schwarzes Rechteck.
    Der Sinn der nächsten Anweisung ist anscheinend dafür zu sorgen, dass mindestens eine halbe Sekunde (500 ms) vergeht, bevor du aufräumst und zum nächsten GameMode-Block wechselst. Hier ist auch dein Problem, denn das was du willst ist aus den folgenden Gründen nicht sichergestellt:

    1. Die Ausführungszeit von playSound() ist anscheinend weit über 500 ms. So wie du es schilderst, sind es ein paar Sekunden. Das ist auch der Grund, wieso mit der momentanen Logik das Warten ausschließlich mit playSound() funktioniert.
    2. Die Verzweigung sollte eigentlich eine Schleife sein, die solange wartet, bis mindestens die gewollte Zeit verstrichen ist.

    Mit einer Fallunterscheidung kann man das Problem nochmal verdeutlichen:

    Fall 1: 'System.currentTimeMillis()' ist kleiner als 'waitingStartTime + 500'
    Dieser Fall tritt ein, wenn playSound() nicht zuvor aufgerufen wird, da es die einzige Routine ist, die mehrere Sekunden braucht.
    Was passiert, ist folgendes: Der if-Block der Verzweigung wird nicht aufgerufen und folglich wird auch nicht in den nächsten Modus gewechselt.
    Alle anderen Durchläufe des aktuellen Blocks werden gleich ablaufen und damit ist es effektiv eine unendliche Schleife, die nur durch einen Zufall wieder Verlassen werden kann, nämlich falls durch einen zufälligen "Hänger", der nächste Fall eintritt:

    Fall 2: 'System.currentTimeMillis()' ist größer oder gleich 'waitingStartTime + 500'
    Dieser Fall tritt ein, wenn playSound() zuvor aufgerufen wird, aus bereits erläutertem Grund.
    Im Gegensatz zum ersten Fall, ist hier die Bedingung der Verzweigung erfüllt und so wird auch ihr if-Block aufgerufen und der Modus gewechselt.
    Das ist das, was du von vorne herein wolltest.

    Code ( Java):
     
    else if(GameMode==1) 
    {
        waitingStartTime = System.currentTimeMillis();
        playSound();  
        zeichneSchwarz(g);
     
        // falls noch keine 500 ms verstrichen sind, warte solange
        while (System.currentTimeMillis() < waitingStartTime + 500);
        // oder um eventuellen zukünftigen Bugs vorzubeugen, kannst du auch einen 
        // leeren Rumpf angeben, was auch als guter Stil angesehen wird:
        // while (System.currentTimeMillis() < waitingStartTime + 500) {};
     
        // werden in jedem Fall ausgeführt
        stopSound();
        GameMode = 2;
    }
     


    Die kleine Änderung oben führt schließlich dazu, dass der Modus in jedem Fall gewechselt wird.

    Beachte aber, dass playSound() mehrere Sekunden zum Ausführen benötigt, die halbe Sekunde (500 ms) in der Bedingung also in Verbindung mit playSound() vollkommen irrelevant ist. Wenn du z.B. 2 Sekunden warten willst, dann ändere '500' zu '2000'.

    Zitat Zitat von ~Cloud~ Beitrag anzeigen
    Hab jetzt das von dir mal getestet mit t.sleep(); Kommt das gleiche Problem das sleep wird VOR dem zeichneSchwarz(); ausgeführt!
    Als erstes sollte man festhalten, dass Thread.sleep() eine statische Methode ist, die immer für den aktuellen Thread gilt.
    Anweisungen wie 'Thread t = Thread.currentThread(); t.sleep(...);' oder 'Thread.currentThread().sleep(...);', die auf Instanzen arbeiten, sind also unnötig und schlechter Stil.

    Was dein Problem angeht, liegt es daran, dass Javas rendering routinen in einem eigenen Thread laufen. (Oder zumindest wird nicht direkt gezeichnet, sondern verzögert, was z.B. eintreten kann, wenn das Betriebssystem Entscheidungen darüber trifft, wann gezeichnet werden soll und wann nicht.) Was passiert ist also folgendes:
    zeichneSchwarz() beauftragt den Rendering-Thread ein schwarzes Rechteck zu zeichnen und dieser wird dem auch nachgehen, sobald er dran kommt.
    Als nächstes legst du den aktuellen Thread schlafen, er wird aber nicht unterbrochen wie bei Thread.yield() (andere Threads werden also nicht ausgeführt), was im Endeffekt dazu führt, dass zuerst gewartet wird und erst danach gezeichnet.

    Noch was zu Thread.sleep(): Wenn du exakte Wartezeiten zwischen Ausführungen haben willst, solltest du darauf verzichten, denn Thread.sleep() wartet nicht exakt, sondern mindestens, so dass es tatsächlich viele Millisekunden mehr sind, die verstreichen.

    Hier sind noch weitere Informationen zu Thread.sleep(), falls es dich interessiert.

    Eigentlich solltest du gänzlich auf blockierenden Code verzichten, falls es möglich ist, und deine Programmlogik entsprechend umstrukturieren, denn blockierender Code wird als sehr schlechter Stil angesehen, aus guten Gründen. Aber als Anfänger kann man sich sowas ruhig leisten, man wächst schließlich erst mit seinen Fehlern. ;)

    Zitat Zitat von Drakes Beitrag anzeigen
    Natürlich gibt es switch, aber ich habe gehört, dass es zumindest in C/C++ langsamer ist als if-else-if.
    Dann hast du etwas falsches gehört, denn das ist Unsinn. Im Worst Case-Szenario entsprechen Switch Cases einer If-Else-Verzweigung, können aber bei klug gewählten Case-Argumenten als einfache Jump-Anweisungen realisiert werden, was sehr schnell ist und keine Branch Mispredictions zur Folge haben kann. Im Grunde kann man besonders bei vielen Cases mit Switches also nur gewinnen.

    Geändert von Kyuu (21.07.2009 um 15:49 Uhr)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •