Thread beenden

Schlagdraufunschluss_124

Aktives Mitglied
Ich bin schon seit einiger Zeit wieder an einem Problem:
Ich will in einer PlayeranimationKLasse eine Animation in einem Thread ausführen lassen.Das Thread wird von einer KeyHandlerKlasse aufgerufen.
-> KeyPressed = start();
...Animieren...
-> KeyReleased = stop();
Allerdings bekomme ich es nicht hin, den Thread, sobald er einmal in der WhileAnimierenSchlaufe ist per Interrupt() zu beenden und die Animation läuft bis zum Schluss zu ende, obwohl ich eben schon vorher die Taste losgelassen habe.

Klasse KeyHandler
Java:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class KeyHandler implements KeyListener {

    private Data data;
    private PlayerAnimation plAnimation;
    private int x = 0;
    private int y = 0;

    private int animationDirec = 0;
    private boolean inThread = false;

    public KeyHandler(Data data, Spiel spiel) {
        this.data = data;
        PlayerAnimation plAnimation = new PlayerAnimation(spiel, this);
        this.plAnimation = plAnimation;

    }

    @Override
    public void keyPressed(KeyEvent e) {

        // UP - Case 2
        if (e.getKeyCode() == KeyEvent.VK_UP) {
            y -= 2;
            data.setAdd_Y(y);

            animationDirec = 2;
            plAnimation.setAnimationDirec(animationDirec);

            if (inThread == false) {
                inThread = true;
                new Thread(plAnimation).start();
            }
        }

        // DOWN - Case 1
        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            y += 2;
            data.setAdd_Y(y);

            animationDirec = 1;
            plAnimation.setAnimationDirec(animationDirec);

            if (inThread == false) {
                inThread = true;

                new Thread(plAnimation).start();

            }
        }
        if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            x -= 2;
            data.setAdd_X(x);

            animationDirec = 3;
            plAnimation.setAnimationDirec(animationDirec);

            if (inThread == false) {
                inThread = true;
                new Thread(plAnimation).start();
            }

        }
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            x += 2;
            data.setAdd_X(x);

            animationDirec = 4;
            plAnimation.setAnimationDirec(animationDirec);

            if (inThread == false) {
                inThread = true;
                new Thread(plAnimation).start();
            }

        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_UP) {
            for (int i = 0; i <= 1; i++) {
                plAnimation.interrupt();
            }
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    public boolean getInThread() {
        return inThread;
    }

    public void setInThread(boolean inThread) {
        this.inThread = inThread;

    }

}

Klasse Animation
Java:
import java.util.Timer;
import java.util.TimerTask;

public class PlayerAnimation extends Thread {

    private KeyHandler keyHandler;
    private Spiel spiel;
    private boolean inThread;
    private int animationDirec;
    private final long threadSleep = 90;

    public PlayerAnimation(Spiel spiel, KeyHandler keyHandler) {
        this.spiel = spiel;
        this.keyHandler = keyHandler;
    }

    @Override
    public void run() {
        switch (this.animationDirec) {
        case 1:
            try {
                while (keyHandler.getInThread() == true) {
                    spiel.curAnim = 1;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 2;
                    Thread.sleep(threadSleep);
                    spiel.curAnim =0;
                    Thread.sleep(threadSleep);
                    System.out.println("InTHread"+keyHandler.getInThread());
                    keyHandler.setInThread(false);
                  
                }
                break;
            } catch (InterruptedException e) {

                e.printStackTrace();

            }
        case 2:
            try {
                while (keyHandler.getInThread() == true ) {
                    spiel.curAnim = 3;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 4;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 5;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 6;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 7;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 8;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 9;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 10;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 11;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 12;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 13;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 14;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 3;
                    Thread.sleep(threadSleep);
                    keyHandler.setInThread(false);
                }
                break;
            } catch (InterruptedException e) {
                interrupt();
                e.printStackTrace();

            }
        case 3:
            try {
                while (keyHandler.getInThread() == true) {

                    spiel.curAnim = 7;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 8;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 6;
                    Thread.sleep(threadSleep);
                    keyHandler.setInThread(false);
                }
            } catch (InterruptedException e) {

                e.printStackTrace();

            }
        case 4:
            try {
                while (keyHandler.getInThread() == true) {

                    spiel.curAnim = 10;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 11;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 9;
                    Thread.sleep(threadSleep);
                    keyHandler.setInThread(false);
                }
            } catch (InterruptedException e) {

                e.printStackTrace();

            }

       /* case 5:

            if (spiel.curAnim >= 0 && spiel.curAnim <= 2) {
                spiel.curAnim = 0;
            } else if (spiel.curAnim >= 3 && spiel.curAnim <= 5) {
                spiel.curAnim = 3;
            } else if (spiel.curAnim >= 6 && spiel.curAnim <= 8) {
                spiel.curAnim = 6;
            } else if(spiel.curAnim >= 9 && spiel.curAnim <= 11){
                spiel.curAnim = 9;
            }*/

        }
    }

    // GETTER/SETTER

    public void setAnimationDirec(int animationDirec) {
        this.animationDirec = animationDirec;
    }

}

Wo liegt mein Fehler ?
 
Probier mal statt
new Thread(plAnimation).start(); // das erzeugt einen neuen Thread und du hast keinen Zeiger darauf.
das hier:
plAnimation.start(); // das ist vermutlich eher was du machen willst

Deine Klasse PlayerAnimation erweiter ja Thread, aber als argument verwendet ist es nur noch ein Runnable und dein call zu interrupt gehts ins leere, weil der eigentliche Thread anonym ist.

Cheers,
Andy
 
Ok. Leider gibt die Konsole jetzt "java.lang.InterruptedException: sleep interrupted" aus.
Wenn ich erneut in die Animation gehen will, dann funtioniert sie nicht mehr und das Programm bleibt beim zuletzt gerenderten BIld stehen.
 
Mein Rat in solchen Faellen ist es immer erst mal die Javadocs zu lesen. In der Docu fuer Thread.start steht unter anderem: "It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution."
Das heisst, du musst erst eine neue Instanz erzeugen und diese dann starten.

Die Javadocs gibt's online ( https://docs.oracle.com/javase/8/docs/api/ ) oder auch hier als Windows help file: https://javadoc.allimant.org/ (fuer Linux gibt's auch einen Viewer fuer das Format).

Have fun,
Andy
 
Warum überhaupt mit der dicken Keule?

Mach doch in deinen Animations-Thread eine Methode stop() und dort setzt du dann eine Variable stopped = true. Innerhalb der Schleife fragst du ab ob stopped gesetzt ist und beendest dann die Schleife und den Thread ganz sauber.

Gruß

Claus
 
Meinst du etwa so ?

Java:
public class PlayerAnim extends Thread{

run() {
while(isRunning){
//Animieren
}
}
stop(){
isRunning = false;
}
}

So funktionierts nämlich leider nicht :/ -> Die Animation geht trotzdem erstmal zuEnde.

Java:
import java.util.Timer;
import java.util.TimerTask;

public class PlayerAnimation extends Thread {

    private KeyHandler keyHandler;
    private Spiel spiel;
    boolean inThread;
    private int animationDirec;
    private final long threadSleep = 200;

    public PlayerAnimation(Spiel spiel, KeyHandler keyHandler) {
        this.spiel = spiel;
        this.keyHandler = keyHandler;
    }

    @Override
    public void run() {
        switch (this.animationDirec) {
        case 1:
            try {
                while (getInThread()) {
                    spiel.curAnim = 1;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 2;
                    Thread.sleep(threadSleep);
                    spiel.curAnim =0;
                    Thread.sleep(threadSleep);
                    //System.out.println("InTHread"+inThread);
                
                }
            
            } catch (InterruptedException e) {
                endThread();
                e.printStackTrace();

            }
        case 2:
            try {
                while (getInThread()) {
                    spiel.curAnim = 3;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 4;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 5;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 6;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 7;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 8;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 9;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 10;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 11;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 12;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 13;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 14;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 3;
                    Thread.sleep(threadSleep);
                    keyHandler.setInThread(false);
                }
            
            } catch (InterruptedException e) {
                endThread();
                e.printStackTrace();
            
            

            }
        case 3:
            try {
                while (keyHandler.getInThread() == true) {

                    spiel.curAnim = 7;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 8;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 6;
                    Thread.sleep(threadSleep);
                    keyHandler.setInThread(false);
                }
            } catch (InterruptedException e) {

                e.printStackTrace();

            }
        case 4:
            try {
                while (keyHandler.getInThread() == true) {

                    spiel.curAnim = 10;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 11;
                    Thread.sleep(threadSleep);
                    spiel.curAnim = 9;
                    Thread.sleep(threadSleep);
                    keyHandler.setInThread(false);
                }
            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        case 5:

            if (spiel.curAnim >= 0 && spiel.curAnim <= 2) {
                spiel.curAnim = 0;
            } else if (spiel.curAnim >= 3 && spiel.curAnim <= 5) {
                spiel.curAnim = 3;
            } else if (spiel.curAnim >= 6 && spiel.curAnim <= 8) {
                spiel.curAnim = 6;
            } else if(spiel.curAnim >= 9 && spiel.curAnim <= 11){
                spiel.curAnim = 9;
            }

        }
    
    }
    public void endThread(){
        setInThread(false);
    }
    public void startThread(){
        setInThread(true);
        new Thread(this).start();
    }
 
 
 


    // GETTER/SETTER

    public void setAnimationDirec(int animationDirec) {
        this.animationDirec = animationDirec;
    }
    public boolean getInThread(){
        return inThread;
    }
    public void setInThread(boolean inThread){
        this.inThread = inThread;
        System.out.println("INTHREAD "+getInThread());
    }

 

}



KEYHANDLER (Hab des mit dem Start auch grad gelesen 🙂 )

Java:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class KeyHandler implements KeyListener {

    private Data data;
    private PlayerAnimation plAnimation;
    private int x = 0;
    private int y = 0;

    private int animationDirec = 0;
    private boolean inThread = false;

    public KeyHandler(Data data, Spiel spiel) {
        this.data = data;
        PlayerAnimation plAnimation = new PlayerAnimation(spiel, this);
        this.plAnimation = plAnimation;

    }

    @Override
    public void keyPressed(KeyEvent e) {

        // UP - Case 2
        if (e.getKeyCode() == KeyEvent.VK_UP) {
            y -= 2;
            data.setAdd_Y(y);

            animationDirec = 2;
            plAnimation.setAnimationDirec(animationDirec);

            if (inThread == false) {
                inThread = true;
                plAnimation.startThread();
                System.out.println("StartenUP");
            }
         
         
        }

        // DOWN - Case 1
        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            y += 2;
            data.setAdd_Y(y);

            animationDirec = 1;
            plAnimation.setAnimationDirec(animationDirec);

            if (inThread == false) {
                inThread = true;
                plAnimation.startThread();
                System.out.println("StartenDown");

            }
        }
        if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            x -= 2;
            data.setAdd_X(x);

            animationDirec = 3;
            plAnimation.setAnimationDirec(animationDirec);

            if (inThread == false) {
                inThread = true;
                new Thread(plAnimation).start();
            }

        }
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            x += 2;
            data.setAdd_X(x);

            animationDirec = 4;
            plAnimation.setAnimationDirec(animationDirec);

            if (inThread == false) {
                inThread = true;
                new Thread(plAnimation).start();
            }

        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_UP) {
            plAnimation.endThread();
            inThread = false;
            System.out.println("BeendenUP");
         
         
        }
        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            plAnimation.endThread();
            inThread = false;
            System.out.println("BeendenDOWN");
         
        }
     
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    public boolean getInThread() {
        return inThread;
    }

    public void setInThread(boolean inThread) {
        this.inThread = inThread;

    }

}
 
Zuletzt bearbeitet:
So funktionierts nämlich leider nicht :/ -> Die Animation geht trotzdem erstmal zuEnde.

Hi,

das Problem ist, dass dein Thread die Aenderung der Kontrollvariable nicht sieht, da diese ja auf dem Hauptthread gemacht wird:

private boolean inThread = false;

Das Keyword volatile wird vermutlich dieses Problem loesen:
private volatile boolean inThread = false;

Mehr darueber hier:
https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html

Cheers,
Andy
 
Mmmh... Ich denke, dass ich das Grundproblem gelöst haben sollte.
ABER:
Wenn ich irgendwie zu oft die Richtung des Spielers wechsle, animiert der Thread zwei Richtungen gleichzeitig, was ziemlich buggy aussieht 🙂

Java:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class KeyHandler implements KeyListener {

    private Data data;
    private PlayerAnimation plAnimation;
    private PlayerPos plPos;
    private int x = 0;
    private int y = 0;

    private int animationDirec = 0;
    private volatile boolean inThread = false;

    public KeyHandler(Data data, Spiel spiel) {
        this.data = data;
        PlayerAnimation plAnimation = new PlayerAnimation(spiel, this);
        this.plAnimation = plAnimation;

        PlayerPos plPos = new PlayerPos(this);
        this.plPos = plPos;

    }

    @Override
    public void keyPressed(KeyEvent e) {

        // DOWN - Case 1
        if (e.getKeyCode() == KeyEvent.VK_DOWN) {

            if (getInThread() == false) {
                setInThread(true);

                animationDirec = 1;

                plPos.setCurrentDirection(animationDirec);
                plPos.startThread();

                /*
                 * y += 2; data.setAdd_Y(y);
                 */
               
                plAnimation.setAnimationDirec(animationDirec);
                plAnimation.startThread();
               
                System.out.println("StarteDOWN"+ getInThread());

            }

        }

        // UP - Case 2
        if (e.getKeyCode() == KeyEvent.VK_UP) {
           
            if (getInThread() == false) {
                setInThread(true);

                animationDirec = 2;

                plPos.setCurrentDirection(animationDirec);
                plPos.startThread();

                /*
                 * y += 2; data.setAdd_Y(y);
                 */

                plAnimation.setAnimationDirec(animationDirec);
                plAnimation.startThread();
                System.out.println("StarteUP"+ getInThread());

            }

        }
        //LEFT - Case 3
        if (e.getKeyCode() == KeyEvent.VK_LEFT) {
           
            if (getInThread() == false) {
                setInThread(true);

                animationDirec = 3;

                plPos.setCurrentDirection(animationDirec);
                plPos.startThread();

                /*
                 * y += 2; data.setAdd_Y(y);
                 */

                plAnimation.setAnimationDirec(animationDirec);
                plAnimation.startThread();

            }

        }
        //RIGHT - Case 4
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
   
            if (getInThread() == false) {
                setInThread(true);

                animationDirec = 4;

                plPos.setCurrentDirection(animationDirec);
                plPos.startThread();

                /*
                 * y += 2; data.setAdd_Y(y);
                 */

                plAnimation.setAnimationDirec(animationDirec);
                plAnimation.startThread();

            }
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_UP) {
            plPos.endThread();
            plAnimation.endThread();
            setInThread (false);
            System.out.println("BeendenUP"+getInThread());

        }
        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            plPos.endThread();
            plAnimation.endThread();
            setInThread (false);
            System.out.println("BeendenDOWN"+getInThread());

        }
        if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            plPos.endThread();
            plAnimation.endThread();
            setInThread (false);

        }
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            plPos.endThread();
            plAnimation.endThread();
            setInThread (false);

        }

    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    public boolean getInThread() {

        return inThread;
    }

    public void setInThread(boolean inThread) {
        this.inThread = inThread;

    }

    public void setPos_X(int x) {
        this.x = x;

    }

    public void setPos_Y(int y) {
        this.y = y;

    }

    public int getPos_X() {
        return x;
    }

    public int getPos_Y() {
        return y;
    }

}


Java:
import java.util.Timer;
import java.util.TimerTask;

public class PlayerAnimation extends Thread {

    private KeyHandler keyHandler;
    private Spiel spiel;
    private boolean inThread;
    private int animationDirec;
    private final long threadSleep = 90;

    public PlayerAnimation(Spiel spiel, KeyHandler keyHandler) {
        this.spiel = spiel;
        this.keyHandler = keyHandler;
    }

    @Override
    public void run() {
        switch (this.animationDirec) {

        // DOWN
        case 1:
            try {
                while (keyHandler.getInThread()) {
                    for (int i = 0; i < 3; i++) {
                        spiel.curAnim = i;
                        Thread.sleep(threadSleep);

                        if (keyHandler.getInThread() == false) {
                            spiel.curAnim = 0;
                            break;

                        }

                    }
                }

            } catch (InterruptedException e) {
                e.printStackTrace();

            }
            break;

        // UP
        case 2:
            try {
                while (keyHandler.getInThread()) {
                    for (int i = 3; i < 14; i++) {
                        spiel.curAnim = i;
                        Thread.sleep(threadSleep);

                        if (keyHandler.getInThread() == false) {
                            spiel.curAnim = 3;
                            break;

                        }

                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();

            }
            break;

        case 3:
            try {
                while (keyHandler.getInThread()) {
                    for (int i = 3; i < 14; i++) {
                        spiel.curAnim = i;
                        Thread.sleep(threadSleep);

                        if (keyHandler.getInThread() == false) {
                            spiel.curAnim = 3;
                            break;

                        }

                    }
                }
            } catch (InterruptedException e) {

                e.printStackTrace();

            }
        case 4:
            try {
                while (keyHandler.getInThread()) {
                    for (int i = 3; i < 14; i++) {
                        spiel.curAnim = i;
                        Thread.sleep(threadSleep);

                        if (keyHandler.getInThread() == false) {
                            spiel.curAnim = 3;
                            break;

                        }

                    }
                }
            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

    public void endThread() {
        setInThread(false);
    }

    public void startThread() {
        setInThread(true);
        new Thread(this).start();
    }

   

    // GETTER/SETTER

    public void setAnimationDirec(int animationDirec) {
        this.animationDirec = animationDirec;
    }

    public boolean getInThread() {
        return inThread;
    }

    public void setInThread(boolean inThread) {
        this.inThread = inThread;
    }

}

Was geht nun schon wieder schief ??😳
 
Also dein Konzept ist einfach Mist. Bei jeder Richtungsänderung den Thread killen und einen neuen starten ist ja vollkommen sinnfrei.

Auch hier würde ich einfach dem Thread mitteilen, das er halt die Richtung ändern muss indem ich eine Variable setze...
 
Cool danke an euch alle !!!! 😀

Es hat geklappt! Hat wohl wirklich an meinem Konzept und dem volatile gelegen...(der junge Padawan hat noch viel zu lernen 😉)

Hier UP (1) und DOWN (2) als BSP.
Java:
import java.util.Timer;
import java.util.TimerTask;

public class PlayerAnimation extends Thread {

    private KeyHandler keyHandler;
    private Spiel spiel;
    private boolean inThread;
    private volatile int animationDirec;
    private final long threadSleep = 90;

    public PlayerAnimation(Spiel spiel, KeyHandler keyHandler) {
        this.spiel = spiel;
        this.keyHandler = keyHandler;
        this.start();
    }

    @Override
    public void run() {
        while (true) {
            switch (this.animationDirec) {
            case 1:
                try {
                    for (int i = 0; i < 3; i++) {
                        spiel.curAnim = i;
                        Thread.sleep(threadSleep);
                        if (keyHandler.getInThread() == false) {
                            spiel.curAnim = 0;
                            break;
                        }
                    }
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                break;

            case 2:
                try {

                    for (int i = 3; i < 14; i++) {
                        spiel.curAnim = i;
                        Thread.sleep(threadSleep);
                        if (keyHandler.getInThread() == false) {
                            spiel.curAnim = 3;
                            break;
                        }
                    }
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                break;

            }
        }
    }

    public void endThread() {
        setInThread(false);
    }

    public void startThread(int animDirec) {
        setInThread(true);
        setAnimationDirec(animDirec);
    }

    // GETTER/SETTER

    public void setAnimationDirec(int animationDirec) {
        this.animationDirec = animationDirec;
    }

    public boolean getInThread() {
        return inThread;
    }

    public void setInThread(boolean inThread) {
        this.inThread = inThread;
    }

}
Unten steht halt noch bissle Quatsch...
 
Zuletzt bearbeitet:

Zurück
Oben