Java Thread will sich nicht beenden

Musicon

Lt. Commander
Registriert
Okt. 2011
Beiträge
1.035
HAllo zusammen,

nach langer Abstinenz hab ich mal wieder versucht nen kleines Tool zu schreiben was mir Massenbewegungen(später auch Klicks) Simulieren soll.

Momentan scheitere ich an dem einfach schließen eines Threads, könnte mir jemand auf die Sprünge helfen, es ist schon sehr lange her ^^

Genau gesagt, bei Klick auf den "ende" Button, soll der Thread einfach dicht machen...

Hab es mit Booleans versucht und mit interupted, aber iwi hab ich das Gefühl es scheitert an etwas elementaren...

Code:
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class mouse extends Thread implements ActionListener
{
   
    private JButton button;
    private JButton button1;
    private boolean event = false;
    JPanel panel1 = new JPanel();
    private boolean canGo=true;
    private boolean session=true;
    public mouse(boolean session) {
       
    }
   
    public mouse()
    {

        // Fenster anlegen
        JFrame frame = new JFrame();
        frame.setTitle("KlickerGO");
        frame.setLayout(new BorderLayout());
       
        // Button anlegen
        button = new JButton("Start");
        button.setBackground(Color.GREEN);
        button1 = new JButton("Stop");
        button.setBackground(Color.RED);
        // Eventhandler für Button zuweisen
        button.addActionListener(this);
        button1.addActionListener(this);
       
       
        panel1.setLayout( new BorderLayout() );
        panel1.add(button, java.awt.BorderLayout.NORTH);
        panel1.add(button1, java.awt.BorderLayout.SOUTH);
       
        // Button der Frame hinzufügen
        frame.add(panel1);
       
        // Fenster zentrieren
        frame.setSize(350,150);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
       
        // Fenster sichbar machen
        frame.setVisible(true);
    }

   
    public static void main(String[] args)   {
        new mouse();}

     

    public void run()
    {
        Robot rob;
        while(canGo)
        {  
            System.out.println("Tick!");
            try {
                rob = new Robot();
                rob.mouseMove(20,20); // Mauszeiger bewegen
                rob.mouseMove(60,60); // Mauszeiger bewegen
                rob.delay(5000); // warte 20 Sekunden 20000
            } catch (AWTException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }      
    }

    public void kill() {
        this.canGo = false;
        System.out.println("ENDE!");
        this.interrupt();
    }
   
    @Override
    public void actionPerformed(ActionEvent e)
    {
        if(e.getSource() == button) {
            Thread t = new mouse(true);
              t.start();          
       } else if(e.getSource() == button1) {
            kill();
       }
       
   }
   
}
 
Du erzeugst 2 mal eine Instanz von mouse.
Und kill() setzt canGo aus der Instanz die du in der main anlegst.
Aber die Instanz die bei actionPerformed erzeugt wird, bekommt davon nichts mit.
 
hab ich mir schon so gedacht, hast du eine Lösung?
warum ich das so tue : wenn ich es über 1 Konstruktor laufen lasse, dann erzeugt er mir ein 2 Fenster, beim Klicken auf den Button "Start", dass soll verhindert werden.

Damit habe ich mein Problem wohl nur verschoben?
Jemand ne Idee für eine Lösung? Ergebnis soll einfach sein EIN Fenster und mit den buttons Threads anstoßen und schließen.

Lg
 
Du mischt da ja ne ganze Menge zusammen. Versuche mal die Objekte besser zu trennen. Also z.B. eine Klasse "MouseMove" (die in einem eigenen Tread läuft) und die GUI. Versuche NICHT von Thread abzuleiten, das ist foo! Und "interrupt" sollte auch nicht aufgerufen werden. Einen Thread braucht definierte Ausstiegspunkte um beendet zu werden.
 
gute Idee:

Code:
    @Override
    public void actionPerformed(ActionEvent e)
    {
        if(e.getSource() == button) {
            Thread t = new mousemove();
              t.start();           
       } else if(e.getSource() == button1) {
            kill();
       }
        
   }

und dann die neue Klasse, somit habe ich 2 Saubere Objekte, aber der Thread reagiert trotzdem nicht auf das False, wwarum nicht?

Code:
public class mousemove extends Thread {
    boolean canGo=true;
    public void run()
    {
        Robot rob;
        while(canGo)
        {   
            System.out.println("Tick!");
            try {
                rob = new Robot();
                rob.mouseMove(20,20); // Mauszeiger bewegen
                rob.mouseMove(60,60); // Mauszeiger bewegen
                rob.delay(5000); // warte 20 Sekunden 20000
            } catch (AWTException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }       
    }
    public void kill() {
        canGo = false;
        System.out.println("ENDE!");
    }
}
 
@Musicon Du darfst das Thread-Object nicht einfach erzeugen und starten. du brauchst die Referenz darauf. Lass mal "mousemove" nicht von Thread erben, sondern nur Runnable implementieren. Also:
Java:
public class MouseMove implements Runnable {
    boolean canGo;
    public void run()
    {
        canGo = true;
        Robot rob;
        while(canGo)
        {   
            System.out.println("Tick!");
            try {
                rob = new Robot();
                rob.mouseMove(20,20); // Mauszeiger bewegen
                rob.mouseMove(60,60); // Mauszeiger bewegen
                rob.delay(5000); // warte 20 Sekunden 20000
            } catch (AWTException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }       
    }
    public void kill() {
        canGo = false;
        System.out.println("ENDE!");
    }
}

Dann kannst du das "MouseMove" im Konstruktor erzeugen und die Action erzeugt nur den Thread mit dem Runnable. sonst verlierst du die Referenz und kannst das Flag nicht mehr setzen.
 
@phm666 : danke, genau das mit den Referenzen hab ich mir schon gedacht, in der Theorie bin ich voll bei dir :)
Leider funktioniert es imme rnoch nicht, obwohl ich nun aus dem Listener nur noch Starte:

Code:
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;



public class mouse extends mousemove implements ActionListener
{
   
    private JButton button;
    private JButton button1;
    private boolean event = false;
    JPanel panel1 = new JPanel();
    private boolean session=true;
    mousemove test;
    Thread thread;

   
    public mouse()
    {

        test = new mousemove ();
        thread = new Thread (test);

        // Fenster anlegen
        JFrame frame = new JFrame();
        frame.setTitle("KlickerGO");
        frame.setLayout(new BorderLayout());
       
        // Button anlegen
        button = new JButton("Start");
        button.setBackground(Color.GREEN);
        button1 = new JButton("Stop");
        button.setBackground(Color.RED);
        // Eventhandler für Button zuweisen
        button.addActionListener(this);
        button1.addActionListener(this);
       
       
        panel1.setLayout( new BorderLayout() );
        panel1.add(button, java.awt.BorderLayout.NORTH);
        panel1.add(button1, java.awt.BorderLayout.SOUTH);
       
        // Button der Frame hinzufügen
        frame.add(panel1);
       
        // Fenster zentrieren
        frame.setSize(350,150);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
       
        // Fenster sichbar machen
        frame.setVisible(true);
    }

   
    public static void main(String[] args)   {
        new mouse();}



   
    @Override
    public void actionPerformed(ActionEvent e)
    {
        if(e.getSource() == button) {
            thread.start ();
       } else if(e.getSource() == button1) {
            kill();
       }
       
   }
   
}

Code:
import java.awt.AWTException;
import java.awt.Robot;

public class mousemove implements Runnable{
    boolean canGo;
   
    public mousemove() {
//        Thread t = new mousemove();
//          t.start();  
    }
    public void run()
    {
        Robot rob;
        canGo=true;
        while(canGo)
        {  
            System.out.println("Tick!");
            try {
                rob = new Robot();
                rob.mouseMove(20,20); // Mauszeiger bewegen
                rob.mouseMove(60,60); // Mauszeiger bewegen
                rob.delay(5000); // warte 20 Sekunden 20000
            } catch (AWTException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }      
    }
    public void kill() {
        canGo = false;
        System.out.println("ENDE!");
    }
}

habe auch versucht "thread = new Thread (test);" im Listener vor t.star(), leider auch ohne erfolg.
 
@Musicon Jetzt bist du nicht mehr weit von der Lösung entfernt. Der Thread interessiert dich ja nicht, daher kannst du in der "actionPerformed"-Methode einfach sagen:
Java:
Thread t = new Thread(test);
t.start();
Einen Thread kann man eh nur einmal starten, daher ist es eh nicht sinnvoll da noch mehr mit zu machen.
Jetzt musst du nurnoch überlegen, welche "kill"-Methode du aufrufen musst. Du hast ja zwei Stück im Code... ;-)
 
ah du lieber gott...... ich habe immer versucht t.kill() zu starten, was es logischerweise nicht gegeben hat, da es kill nur mousemove sein sollte, aber ich so festgefahren war, dass immer ein kill von Thread ausführen wollte was es natürlich nicht gab und kill dann logischerweise von mouse gefeuert wurde und DORT wurde die Vari tatsächlich richtig gesetzt ;P

naja sehr lange her bei mir, DANKE!

Falls du noch lust hast... was war der genau unterschied zwischen extends Thread und Runable bzw. verwendungsszenarien?

LG
 
Zuletzt bearbeitet:
Man sollte Runnable statt Thread erweitern um flexibler zu bleiben. Du kannst das Runnable auch mit einem ExecutorService ausführen, der sich um die Verwaltung der Threads kümmert. Oder auch mit FutureTasks arbeiten, um Threads einfacher zu syncronisieren.
Wichtig ist auch, wenn du Runnable nutzt, kannst du nicht versehentlich die Arbeitsweise des Threads verändern. "stop" ist so eine Methode, die vom Thread gerne auch mal benutzt wird, obwohl sie eigentlich nicht verwendet werden soll. Das passiert natürlich nicht, wenn man Runnable nutzt.
Aber schön, dass es jetzt funktioniert.
 
  • Gefällt mir
Reaktionen: Musicon
Zurück
Oben