Thread beenden in Java

Gast #4454166
Lesenswert?

Hallo zusammen.

Ich habe folgendes Problem: Ich kann zwar in Java einen Thread starten, 
aber irgendwie nicht beenden. Er läuft trotz stop(), interrupt() u.ä. 
einfach weiter.

Könntet ihr mir helfen?

Hier der gekürzte Code:
1
 
2
 Thread test_thread = new Thread (.....);
3
 ..
4
 
5
 
6
 if(e.getSource() == btn_ein)
7
 {
8
   test_thread.start();
9
 }
10
 
11
 
12
 if(e.getSource() == btn_aus)
13
 {
14
   test_thread.interrupt();   // ??? funktioniert nicht, Thread läuft weiter!   
15
 }

Vielen Dank!
Gast #4454194
Lesenswert?

Hi Boris,

ja in der Tat, im Thread selbst ist folgendes geschrieben:
1
public void run() 
2
  {
3
    
4
    while(true)
5
    { ... }
6
        }

Das heißt ich frage in der While-Schleife ab, ob ein gewisses Flag 
gesetzt wird, welches ich dann über eine Variable von "außen" (über das 
Objekt) setze?

Oder wie würde man es am besten machen? Denn die Endlos-Schleife brauche 
ich definitiv bis zu dem Zeitpunkt, wo eben der Thread beendet werden 
soll.

Danke!
Gast #4454201
Lesenswert?

Ahnungsloser schrieb:
> test_thread.start();

Macht man eigentlich nur mit Threads die sich selbst beenden.

Für Threads hast du eigentlich 2 verschiedene Anwendungen

1. Du willst eine Arbeit parallelisieren. Dann musst du auch die 
Ergebnisse zurückbringen und alles synchronisieren.
Dazu solltest du dir Thread Pools anschauen Package: 
java.util.concurrent

2. Du brauchst einen unabhängigen Hintergrundprozess, der undefiniert 
lange läuft. Du implementierst dazu eine eigene Klasse die entweder von 
Thread erbt oder ein entsprechendes Interface implementiert.
Zusätzlich baust du eine Methode ein, die über ein Flag dem Thread 
signalisieren kann dass er sich beenden soll.
In der Hauptschleife des Threads prüfst du regelmäßig auf das Flag und 
beendest dann ggf. die Schleife. Gesetzt wird das Flag vom 
Hauptprogramm, das den Thread instanziiert und gestartet hat.
Gast #4454211
Lesenswert?

Ahnungsloser schrieb:
> public void run()
>   {
>
>     while(true)
>     { ... }
>         }

stell dich doch nicht so an:

1
class MyThread extends Thread {
2
...
3

4
  boolean endThread = false;
5

6
  public void setEndThread() {
7
    endThread = true;
8
  }
9

10
  public void run() {
11

12
    while (!endThread) {
13
      ...
14
    }
15
  }
16
}
Gast #4454323
Lesenswert?

Super, danke, das werde ich gleich mal probieren.
Habe jetzt eine public boolean-Variable in meiner Threadklasse 
implementiert, die dann als Flag von außen schaltbar sein soll und die 
While-Schleife in der Threadklasse beeinflusst.

Jetzt habe ich aber das nächste Problem.
Die Instanziierung erfolgt bei mir über folgenden Befehl:
1
failure_handling = new Thread(new Failure_Msg_Thread(...) )

Die besagte Boolean-Variable liegt in "Failure_Msg_Thread".
Jetzt müsste ich aber ja ein Objekt von "Failure_Msg_Thread" erzeugen, 
um auf die Boolean-Variable zuzugreifen.
Wie kann ich das tun, damit ein Bezug zu failure_handling existiert und 
somit der richtige Thread beendet wird?

Danke!
Gast #4454354
Lesenswert?

du machst eine liste mit thread objekten, und greifst vom hauptprogramm 
aus auf die getter- und setter methoden der threads in der liste zu.
ob die dazu "synchronized" sein müssen (sollten) weiß ich jetzt grad 
nicht :/
Gast #4454404
Lesenswert?

>Was denkst du machst du mit:

Naja ich übergebe dem Konstruktor von Thread ein Objekt, das 
"Failure_Msg_Thread" heißt.
In der Klasse Failure_Msg_Thread ist die besagte Variable, aber ich habe 
vom Objekt "failure_handling" keinen Zugriff darauf.
Ein Objekt von "Failure_msg_Thread" habe ich ja quasi nicht.

Oder irre ich?
Gast #4454422
Lesenswert?

Ahnungsloser schrieb:
> failure_handling = new Thread(new Failure_Msg_Thread(...) )

Sehe ich jetzt erst.

Was soll das?
Ich denke FailureMsgThread() ist abgeleitet von Thread.

Also heisst das
Thread failureHandling = new FailureMsgThread(...);
...
failureHandling.start();

...

// Am Ende:
failureHandling.setEndThread();   // oder wie auch immer du das FLag 
setzt

// jetzt noch etwas warten oder prüfen ob der Thread beendet ist

..


Irgendwie fehlen dir alle Grundlagen. Bevor du multithreaded 
programmierst solltest du die ersten 5 Kapitel von "Java ist auch eine 
Insel" mal durchgelesen und erst mal einfache Programme programmiert 
haben.

Und gewöhne dir bitte die Unterstriche ab und benutze die in Java 
übliche Notationskonventionen für Methoden, Klassen, Variablen und 
Konstanten.
Gast #4454432
Lesenswert?

>Thread failureHandling = new FailureMsgThread(...);

Das funktioniert bei mir schon gleich garnicht..es müsste doch wenn dann
>Failure_Msg_Thread failure_handling = new Failure_Msg_Thread
lauten?!
Gast #4454436
Lesenswert?

Etwas moderner (ok, das Konzept stammt schon aus Anfang der 90er oder 
früher, aber Java hat es spät implementiert) ist es Futures zu 
verwenden.

Leider ist die JavaDoc dafür ziemliche mies

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html

und sowohl die Implementierung also auch die Beispiele die man in 
diversen Tutorien findet verschleiern die Idee mehr als das sie die 
Vorteile zeigen.

Eigentlich geht es um die Idee der Active Objects. Das ist eine Technik 
um Concurrent Programme zu strukturieren. Ein Future ist dabei nur ein 
Hilfsmittel, ein Versprechen (ein Platzhalter) auf ein Ergebnis, das ein 
(Active) Object irgendwann mal liefert. Ein Active Object ist ein 
Objekt, das intern einen oder mehrere Threads verwendet, aber seine 
Außenwelt nicht mit Thread-Details behelligt. D.h. es enkapsuliert 
Threads und regelt alle Thread-Operationen wie Synchronisation, 
Schedulling alleine. Im Gegensatz zu normalen Threads läuft ein Thread 
nicht wild über Objektgrenzen hinweg (wenn man es nicht verpfuscht) und 
Thread-Code ist nicht über die ganze Codebasis verschmiert.

Damit verbunden ist die Idee des asynchronen Methodenaufrufs (hat Booch 
glaube ich schon in den 80ern in seine OO-Methode). Methoden liefern 
nicht sofort ein Ergebnis, sonder verhalten sich asynchron. Sie liefern 
nur ein Versprechen auf ein Ergebnis (ein Future). Der Aufrufer kann das 
eigentliche Ergebnis vom Future erfragen wenn er es benötigt. Das sollte 
der Aufrufer so spät wie möglich machen, um dem Active Object genug Zeit 
zur Berechnung zu geben. In der Zwischenzeit kann der Aufrufer etwas 
anderes machen.


Das Konzept sieht so aus (Code sieht durch die println()s schlimmer aus 
als er ist):
1
import java.util.concurrent.Callable;
2
import java.util.concurrent.CancellationException;
3
import java.util.concurrent.ExecutorService;
4
import java.util.concurrent.Executors;
5
import java.util.concurrent.Future;
6
import java.util.concurrent.FutureTask;
7

8
/**
9
 * Benutzer eines {@link ActiveObject}, der von den Thread-Details
10
 * nichts wissen will oder muss.
11
 */
12
public class Caller {
13
   private static final String myName = Caller.class.getSimpleName();
14

15
  public void foo() {
16
    ActiveObject activeObject = new ActiveObject();
17

18
    //
19
    // Asynchroner Methodenaufruf.
20
    // Liefert kein Ergebnis, sondern ein Versprechen auf ein
21
    // Ergebnis in der Zukunft.
22
    //
23
    System.out.println(myName + ": Calling Method");
24
    System.out.flush();
25
    Future<Integer> future = activeObject.asyncMethod();
26
    System.out.println(myName + ": Got future");
27
    System.out.flush();
28

29
    //
30
    // ... Mach irgendwas anderes ...
31
    //
32
    try {
33
      Thread.sleep(2000);
34
    } catch (InterruptedException e) {
35
    }
36

37
    //
38
      // An einem Punkt wird entweder das Ergebnis benötigt,
39
    // oder es kann weggeworfen werden.
40
    //
41
    boolean needResult = true; //
42

43
    if (needResult) {
44
      try {
45
        System.out.println(myName + ": Asking for result");
46
        System.out.flush();
47
        int result = future.get();
48
        System.out.println(myName + ": Got result: " + result);
49
        System.out.flush();
50
      } catch (Exception e) {
51
        System.err.println(e);
52
      }
53
    } else {
54
      future.cancel(true);
55
      System.out.println(myName + ": Result canceled");
56
      System.out.flush();
57
    }
58
  }
59

60
  public static void main(String[] args) {
61
    new Caller().foo();
62
  }
63
}
64

65
/**
66
 * Aktives Object. Benutzt intern Threads, behelligt den Aufrufer aber nicht mit
67
 * Details. Methoden liefern statt dessen Ergebnisse asynchron zum Aufruf.
68
 */
69
class ActiveObject {
70
  private static final String myName = ActiveObject.class.getSimpleName();
71

72
  /** Interne Threads des {@link ActiveObject} */
73
  private ExecutorService executorS = Executors.newFixedThreadPool(5);
74

75
  /**
76
   * Asynchrone Methode. Kehrt zurueck bevor das Ergebnis berechnet ist.
77
   * 
78
   * @return Ein Versprechen (Future) auf das Ergebnis in der Zukunft.
79
   */
80
  public Future<Integer> asyncMethod() {
81

82
    Callable<Integer> callable = new Callable<Integer>() {
83

84
      /**
85
       * Eigentliche Implementierung der Methode
86
       */
87
      @Override
88
      public Integer call() throws Exception {
89
        int i;
90
        for (i = 0; i < 50; i++) {
91
          Thread.sleep(100);
92
          if (Thread.interrupted()) {
93
            System.out.println(myName + ": Interrupted");
94
            System.out.flush();
95
            // Wahrscheinlichster Grund is Aufruf von cancel(true)
96
            throw new CancellationException();
97
          }
98
          System.out.println(myName + ": " + i);
99
          System.out.flush();
100
        }
101
        return i;
102
      }
103

104
    };
105

106
    FutureTask<Integer> futureTask = new FutureTask<>(callable);
107
    System.out.println(myName + ": Running task");
108
    System.out.flush();
109
    executorS.execute(futureTask); // Starte die Berechnung
110

111
    return futureTask;
112
  }
113
}
Gast #4454442
Lesenswert?

Jay schrieb:
> Etwas moderner (ok, das Konzept stammt schon aus Anfang der 90er oder
> früher, aber Java hat es spät implementiert) ist es Futures zu
> verwenden.

Macht nur Sinn, wenn man mit Threads Berechnungen parallelsieren will 
und die Ergebnisse braucht.
Für einen Thread der unbestimmt lange als "Daemon Thread" neben dem 
Hauptprogramm läuft und erst mal unabhängig werkelt ist das Unsinn.

Ausserdem hab ich daruf oben schon hingewiesen

Der Andere schrieb:
> Dazu solltest du dir Thread Pools anschauen Package:
> java.util.concurrent

Aber der TO kann ja nicht mal eine Klasse von Thread ableiten und die 
dann starten. Also sind Future Callable und Threadpools für ihn soch so 
weit weg wie der Mond.

Ahnungsloser schrieb:
> Das funktioniert bei mir schon gleich garnicht..es müsste doch wenn dann
>>Failure_Msg_Thread failure_handling = new Failure_Msg_Thread
> lauten?!

Siehe meine Korrekur.
Aber auch hier: Grundlagen was ist Polymorphie
https://de.wikipedia.org/wiki/Objektorientierung#Polymorphie
Gast #4454450
Lesenswert?

Da wird doch mit Kanonen auf Spatzen geschossen.
Es muss doch auch mit meinem Code gehen.
Wenn ich ein Objekt von "Failure_Msg_Thread" erzeuge, läuft der Thread 
zwar, aber das Main-Programm hängt sich auf. (Warum auch immer..)

Immerhin hat der Thread bei der "falschen" Notation funktioniert:
>failure_handling = new Thread(new Failure_Msg_Thread
Er lässt sich nur nicht beenden.

Ich verstehe es nicht :(
Gast #4454460
Lesenswert?

Jay schrieb:
> Was er ja wohl will (den Boolean den er haben will). Aber egal, alles
> nicht mein Problem.

Die boolean Variable ist zu Signalisierung dass der Thread sich beenden 
soll.
Dein Problem ist hier eher das verstehende Lesen :-)

Ahnungsloser schrieb:
> Ich verstehe es nicht :(

Dann backe erst mal kleinere Brötchen bis du Klassen und Objekte und 
deren Instanziierung verstanden hast.
Sorry, aber ich muss jetzt mal wieder was arbeiten.
Gast #4454504
Lesenswert?

>Dann backe erst mal kleinere Brötchen bis du Klassen und Objekte und
>deren Instanziierung verstanden hast.

Das habe ich. Sorry für meinen Fehler vorhin...

Sobald ich FailureMsgThread instanziiere und <OBJEKT>.run(); ausführe, 
läuft zwar der Thread bis zum St.Nimmerleinstag, aber das Main-Programm 
hängt sich auf.

Ich schicke jetzt nochmal meinen Code, in der Hoffnung, dass mir jemand 
hilft und mich nicht fertig macht, weil ich ja so ein dummer Anfänger 
bin.

Thread:
1
public class Failure_Msg_Thread implements Runnable 
2
{
3
  public boolean stopThread;
4
  private JLabel overvoltage;
5
  private JLabel overtemperature;
6
  
7
  Failure_Msg_Thread(JLabel overtemperature, JLabel overvoltage);
8
  {
9
    this.overvoltage = overvoltage;
10
    this.overtemperature = overtemperature;
11
    stopThread=false;
12
  }
13
  
14

15
  @Override
16
  public void run() 
17
  {
18
    
19
    while(stopThread != false)
20
    {
21
        try 
22
        {
23
            Thread.sleep(3000);               
24
        }        
25
        
26
        catch(InterruptedException ex) 
27
        {
28
            Thread.currentThread().interrupt();
29
        }
30
        
31
        String fault_detection = LeftRightMid.mid(DeviceInfo, 23,2);
32
        try        
33
        {
34
           if(fault_detection.equals("25")) {overtemperature.setOpaque(true); overtemperature.setBackground(Color.red);}
35
           if(fault_detection.equals("85")) {overvoltage.setOpaque(true); overvoltage.setBackground(Color.red);}
36
        }
37
          
38
        
39
        catch (UnknownHostException e1) 
40
        {
41
          JOptionPane.showMessageDialog(null,"Unknown host!", "Error", JOptionPane.PLAIN_MESSAGE);
42
          
43
          e1.printStackTrace();
44
        } 
45
        
46
        catch (IOException e1) 
47
        {
48
          //JOptionPane.showMessageDialog(null,"No connection!", "Error", JOptionPane.PLAIN_MESSAGE);
49

50
          e1.printStackTrace();
51
        }
52
    }
53
  }
54
}
55

56
(/c]
57

58

59

60

61
Hauptklasse:
62
[c]
63

64
public class ThreadTest extends JFrame implements ActionListener
65
{
66
  
67

68
  //////////// Konstruktor //////////
69
  ThreadTest()
70
  {
71
    .....
72
  }
73
  //////////////////////////////////
74
  
75
  
76
  Failure_Msg_Thread failure_handling = new Failure_Msg_Thread(lbl_Overtemp,lbl_Overvoltage);
77

78
    
79
  if (e.getSource() == btn_StartRC)
80
  {
81
      
82
       failure_handling.run();
83
         
84
  }
85
      
86
  if (e.getSource() == btn_StopRC)
87
  {
88
    /// Hier soll Thread gestoppt werden  
89
  }
90
}


Danke!
Gast #4454573
Lesenswert?

Ahnungsloser schrieb:
> SwingWorker? noch nie gehört.

Dann ist es jetzt Zeit, sich damit anzufreunden, wenn du eh Swing 
machst.

> Das Problem ist, dass der Thread einwandfrei funktioniert: Er lässt sich
> nur nicht schließen/beenden!!!!

Nein, das Problem ist, dass du das Problem nicht kennst, du meinst eine 
Lösung (Thread, wobei, nichtmal das, du implementierst ja "Runnable") zu 
kennen.
Das tritt hier im Forum sehr oft auf, die Leute kommen mit Lösungen 
und nicht mit Problemen.
Dein Problem ist:
Du hast eine Swing-Anwendung und willst irgendwas abbrechbares im 
Hintergrund machen, das sporadisch deine Oberfläche aktualieren soll.
Die Lösung dazu:
SwingWorker
Gast #4454581
Lesenswert?

Ahnungsloser schrieb:
> Sobald ich FailureMsgThread instanziiere und <OBJEKT>.run(); ausführe,

In meinem oben angegebenen Link zum Tutorial wird dir erklärt warum du 
start() und nicht run() aufrufen sollst. run() läuft nämlich im 
Hauptthread und nicht in einem neuen, und da die run() Methode eben 
wartet bis sie ein zeichen zum Beenden kriegt, das sie aber nie kriegen 
kann weil das Programm ja jetzt nicht weiterlaufen kann, hängt das 
Programm.

Nochmal: Ohne Grundlagen hangelst du dich nur von einem Problem zum 
anderen.
Das ist doch wieder mal "programming by copy paste".



Jay schrieb:
> Der Andere schrieb:
>> Dein Problem ist hier eher das verstehende Lesen :-)
>
> Dein Problem ist, dass du ein Arsch bist.

Was du bist zeigst du ganz klar, Unfug schreiben, keine Argumente, dafür 
Beleidigungen.

Jay schrieb:
> Ah, jetzt verschwinden, nachdem du alle Weggebissen hast. Sehr
> sympathisch.

Im Gegensatz zu dir muss ich arbeiten und verdiene damit Geld. Der 
Wadenbeisser passt besser zu dir. Und ich habe wenigstens konkret 
geholfen statt 100 Zeilen viel zu komplexen und nicht zum Problem 
passenden Code einfach einem Anfänger vorzuwerfen.
Ob du selbst den Code verstehst oder nur irgendwo rauskopiert hast weist 
nur du (hoffentlich).
Gast #4454586
Lesenswert?

1
  if (e.getSource() == btn_StartRC)
2
  {
3
      
4
       new Thread(failure_handling).start(); // sonst wird kein Thread gestartet, sondern du führst nur die Run-Methode im aktuellen Thread aus!
5
         
6
  }
7
      
8
  if (e.getSource() == btn_StopRC)
9
  {
10
    /// Thread Bescheid geben, dass er stoppen soll.
11
    failure_handling.stopThread = true;
12
  }
Gast #4454769
Lesenswert?

Ahnungsloser schrieb:
> läuft zwar der Thread bis zum St.Nimmerleinstag
Ist kein Thread, heißt nur so.

> aber das Main-Programm
> hängt sich auf.
Tut es nicht. Es führt die run-Methode Deines Failure_Msg_Thread-Objekts 
aus.
Du erstellst gar keinen Thread und startest auch keinen.
Ein Runnable fängt nicht von selbst an, in einem eigenen Thread zu 
laufen, indem man seine run-Methode aufruft.
Gast #4455377
Lesenswert?

Gestern habe ich noch bis 1 Uhr diesen SwingWorker versucht zu nutzen.
Leider mit noch weniger Erfolg.

Ich nahm die alten Anweisungen der Klasse Failure_Msg_Thread und 
kopierte sie in die "execute()"-Methode.
Die "DoinBackground"-Methode funktionierte garnicht, bei der 
"execute"-Methode habe ich seither den Fehler:
"Cannot override the final method from Swingworker<Integer,Integer>"

Grundgerüst der ThreadKlasse sieht so aus:
1
public class Failure_Msg_Thread extends SwingWorker<Integer, Integer>
2
{
3
  
4
  public boolean stopThread;
5
  
6
  Failure_Msg_Thread()
7
  {
8

9
  }
10
  
11
  
12
  
13
  
14
  public void execute() throws Exception 
15
  {
16
    while(stopThread != true)
17
    {
18
      // Hier sollen die Anweisungen stehen        
19
            
20
    }    
21
  }
22

23

24
  @Override
25
  protected Integer doInBackground() throws Exception 
26
  {
27
    // TODO Auto-generated method stub
28
    return null;
29
  }
30

31
  
32
  
33
}


Im Hauptprogramm rufe ich das Ganze dann mit ".execute()" auf. 
Funktioniert wiegesagt ja nicht, da ein Fehler in der Threadklasse 
vorliegt, den ich nicht zu beheben weiß...

Wisst ihr weiter?

Danke.
Gast #4455397
Lesenswert?

Nachtrag:
1
public class Failure_Msg_Thread extends SwingWorker<Integer, Integer>
2
{
3
  
4
  public boolean stopThread;
5
  
6
  Failure_Msg_Thread()
7
  {
8
      stopThread = false;
9
  }
10
  
11
  public void setStop()
12
  {
13
      stopThread = true;
14
  }
15
  
16
  
17
  @Override
18
  protected Void doInBackground() throws Exception 
19
  {
20
      while(stopThread != true)
21
      {
22
        // Hier steht der Code, der auch ausgeführt wird!              
23
      }   
24
  }
25

26
  
27
  
28
}

Nach meinem Dafürhalten sollte ja jetzt beim Ausführen von 
<OBJEKT>.setStop() das entsprechende Stop-Flag gesetzt werden, damit das 
Ding anhält und nicht mehr ewig weiterläuft.
TUT ES ABER WIEDER NICHT!

So rufe ich es auf:
1
if (e.getSource() == btn_Stop)
2
    {
3
    
4
      Failure_Msg_Thread.setStop();
5
                }

Bin jetzt wirklich mit meinem Latein am Ende und hoffe nun auf eure 
Hilfe!


Gruß
Gast #4455405
Lesenswert?

Ahnungsloser schrieb:
> Die "DoinBackground"-Methode funktionierte garnicht, bei der
> "execute"-Methode habe ich seither den Fehler:

Öhm, wie kommst du auf die Idee execute zu überschreiben? Das ist 
absolut nicht nötig.

Dein Hintergrundzeugs muss natürlich in doInBackground() laufen, die 
Methode heisst ja schon so...
Dieses ganze Gedöns mit dem boolean kannst dir auch sparen, du kannst 
den laufenden Worker jederzeit mit cancel() abbrechen (das steht auch in 
dem verlinkten Beispiel).
Deine JLabel versorgst du aus der Methode process (die du, vielleicht 
etwas ungewohnt, über publish aufrufst):
1
@Override
2
protected void process(List<String> chunks) {
3
    // Messages received from the doInBackground() (when invoking the publish() method)
4
}
Warum du jetzt mit SwingWorker<Integer, Integer> arbeitest und nicht mit 
SwingWorker<Void, Void> oder gar SwingWorker<BigDecimal, String> 
solltest du dir auch nochmal durch den Kopf gehen lassen.
Gast #4455414
Lesenswert?

Und weil du wahrscheinlich nicht von selber drauf kommst:

Nochmal, schmeiss diesen ganzen boolean-kram raus, getter, setter, 
variable, alles.
SwingWorker bietet dir isCancelled() an (die du bitte nicht selber 
implementierst).

In deiner doInBackground() steht dann also als erstes:
1
while(!isCancelled()){
Gast #4455415
Lesenswert?

Hi,

danke für deine Antwort, ich denke meine letzte Antwort hat sich mit 
deiner überschnitten.

Ich prüfe nun in meiner Endlosschleife in der Threadklasse folgendes:
1
protected Void doInBackground() throws Exception   
2
{ 
3
   while(!isCancelled())
4
   {
5
     Thread.sleep(3000);                ///// Polling-Intervall
6
       .....          
7
   }
8
}

Im Hauptprogramm mache ich folgendes:
1
Failure_Msg_Thread fmt = new Failure_Msg_Thread(....);
2

3
if (e.getSource() == btn_StopRC)
4
{  fmt.execute();   }
5

6
if (e.getSource() == btn_StopRC)
7
{    
8
   fmt.cancel(true);
9
}

Es wird jedenfalls NICHT beim Klick auf "Stop" der Thread beendet. Der 
läuft einfach weiter..
Gast #4455455
Lesenswert?

So, ich hab jetzt mal auf die Schnelle ein lauffähiges Beispiel 
gebastelt (Das UI ist schnell in Netbeans geklickt..)
1
import java.util.Iterator;
2
import java.util.List;
3
import javax.swing.SwingWorker;
4

5
public class SwingWorkerTest extends javax.swing.JFrame {
6

7
    public SwingWorkerTest() {
8
        initComponents();
9
    }
10

11
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
12
    private void initComponents() {
13

14
        javax.swing.JPanel southPanel = new javax.swing.JPanel();
15
        buttonStart = new javax.swing.JButton();
16
        buttonStop = new javax.swing.JButton();
17
        scroll = new javax.swing.JScrollPane();
18
        textArea = new javax.swing.JTextArea();
19

20
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
21

22
        southPanel.setLayout(new java.awt.BorderLayout());
23

24
        buttonStart.setText("start");
25
        buttonStart.addActionListener(new java.awt.event.ActionListener() {
26
            public void actionPerformed(java.awt.event.ActionEvent evt) {
27
                buttonStartActionPerformed(evt);
28
            }
29
        });
30
        southPanel.add(buttonStart, java.awt.BorderLayout.WEST);
31

32
        buttonStop.setText("stop");
33
        buttonStop.setEnabled(false);
34
        buttonStop.addActionListener(new java.awt.event.ActionListener() {
35
            public void actionPerformed(java.awt.event.ActionEvent evt) {
36
                buttonStopActionPerformed(evt);
37
            }
38
        });
39
        southPanel.add(buttonStop, java.awt.BorderLayout.LINE_END);
40

41
        getContentPane().add(southPanel, java.awt.BorderLayout.SOUTH);
42

43
        textArea.setColumns(20);
44
        textArea.setRows(5);
45
        scroll.setViewportView(textArea);
46

47
        getContentPane().add(scroll, java.awt.BorderLayout.CENTER);
48

49
        pack();
50
    }// </editor-fold>                        
51

52
    private void buttonStartActionPerformed(java.awt.event.ActionEvent evt) {                                            
53
        buttonStop.setEnabled(true);
54
        buttonStart.setEnabled(false);
55
        worker = new Worker();
56
        worker.execute();
57
    }                                           
58

59
    private void buttonStopActionPerformed(java.awt.event.ActionEvent evt) {                                           
60
        worker.cancel(true);
61
    }                                          
62

63
    private class Worker extends SwingWorker {
64

65
        @Override
66
        protected Object doInBackground() {
67
            int cnt = 0;
68
            while (!isCancelled()) {
69
                publish(Integer.toString(++cnt));
70
                try {
71
                    Thread.sleep(1000);    
72
                } catch (InterruptedException e) {
73
                    break;                 
74
                }
75
            }
76
            return "Stopped."; 
77
        }
78

79
        @Override
80
        protected void process(List display) {
81
            Iterator it = display.iterator();
82
            while (it.hasNext()) {
83
                textArea.append((String) it.next() + "\n");
84
                textArea.setCaretPosition(textArea.getText().length());
85
            }
86
        }
87

88
        @Override
89
        protected void done() {
90
            textArea.append("Stopped.");
91
            textArea.setCaretPosition(textArea.getText().length());
92
            buttonStart.setEnabled(true);
93
            buttonStop.setEnabled(false);
94
        }
95
    }
96

97
    public static void main(String args[]) {
98
        java.awt.EventQueue.invokeLater(new Runnable() {
99
            @Override
100
            public void run() {
101
                new SwingWorkerTest().setVisible(true);
102
            }
103
        });
104
    }
105

106
    private SwingWorker worker;
107
    // Variables declaration - do not modify                     
108
    private javax.swing.JButton buttonStart;
109
    private javax.swing.JButton buttonStop;
110
    private javax.swing.JScrollPane scroll;
111
    private javax.swing.JTextArea textArea;
112
    // End of variables declaration                   
113
}
Gast #4455483
Lesenswert?

Danke für deine Mühe. Aber das löst leider auch nicht mein Problem, da 
ich keinerlei Unterschiede zwischen deinem Code zum Stoppen des 
SwingWorkers..:
1
  @Override
2
        protected Object doInBackground() {
3
            int cnt = 0;
4
            while (!isCancelled()) {
5
                publish(Integer.toString(++cnt));
6
                try {
7
                    Thread.sleep(1000);    
8
                } catch (InterruptedException e) {
9
                    break;                 
10
                }
11
            }
12
            return "Stopped."; 
13
        }

..und meinem erkenne. Wiegesagt, der Swingworker läuft einwandfrei, aber 
er lässt sich (wie auch der Thread) einfach nicht stoppen/beenden:
1
@Override
2
protected Void doInBackground() throws Exception 
3
{        
4
  while(!isCancelled())
5
        {    
6
            Thread.sleep(1000);    
7
             ... Anweisungen...
8
        } return; }

Liegt es denn eventuell an meinem "throws Exception" beim Methodenkopf?
1
protected Void doInBackground() throws Exception


Danke
Gast #4455539
Lesenswert?

Fehler gefunden.

Das Problem lag daran, dass die Instanziierung von "Failure_Msg_Thread" 
außerhalb der beiden IF-Anweisungen im Hauptprogramm erfolgte.

So lässt er sich starten, aber NICHT beenden:
1
public void actionPerformed(ActionEvent e) 
2
{  
3
     fmt = new Failure_Msg_Thread(..);
4

5
     if(e.getSource() == btn_start)
6
     {
7
      fmt.execute();  
8
      ...
9
     }
10

11
     if(e.getSource() == btn_stop)
12
     {
13
      fmt.cancel(true);   // wirkungslos!  
14
      ...
15
     }
16
}


So aber lässt er sich starten und stoppen:
1
public void actionPerformed(ActionEvent e) 
2
{  
3
     
4

5
     if(e.getSource() == btn_start)
6
     {
7
       fmt = new Failure_Msg_Thread(..);
8
       fmt.execute();  
9
      ...
10
     }
11

12
     if(e.getSource() == btn_stop)
13
     {
14
       fmt.cancel(true);   // wirkungslos!  
15
      ...
16
     }
17
}


Das verstehe ich überhaupt nicht. Aber gut..läuft jetzt.

Gruß
Gast #4455650
Lesenswert?

Ahnungsloser schrieb:
> Das verstehe ich überhaupt nicht.

Ich überlass dir das mal als Fleissaufgabe.

> Aber gut..läuft jetzt.

Nur wie halt.
Dein Exceptionhandling ist defacto nicht vorhanden.

Einfach
1
protected Void doInBackground() throws Exception
hinzurotzen sorgt zwar dafür, dass dein Code anstandslos compiled, aber 
eigentlich macht man das anders.
Schau dass du das in der Schleife sauber abfängst mit multicatch (ein 
try, viele catches) und entsprechend passende Meldungen ausgibst und die 
Schleife sauber verlässt.
Gast #4455674
Lesenswert?

>Ich überlass dir das mal als Fleissaufgabe.

Man kann doch in einer Methode ein Objekt erzeugen.
Das Verhalten müsste doch eigentlich genau andersrum sein, dass die 
If-Anweisung von einer anderen If-Anweisung gekapselt ist und ich in der 
zweiten If nichtmal das Objekt der ersten sehen dürfte?!
Gast #4455692
Lesenswert?

Klar und du hast jedesmal ein neues Objekt erzeugt und dieses dann 
angehalten.... aber nicht den Thread der bei einem früheren Aufruf der 
ActionPerformed-Methode erzeugt wurde....

Du solltest mal an den Grundlagen arbeiten..
Persönliche Seite #4456014
Lesenswert?

Ahnungsloser schrieb:
> Liegt es denn eventuell an ...

Das liegt daran das du erst mal ein paar Grundlagen dir aneignen und 
VERSTEHEN solltest! Programmieren ist doch keine Quizshow wo man sich 
munter von Frage zu frage "rät" und im Zweifle den Foren-Joker befragt.

Ahnungsloser schrieb:
> Bin jetzt wirklich mit meinem Latein am Ende

Latein (oder eine andere Sprache, gilt auch für Programmiersprachen) 
lernt man auch nicht dadurch das man sich aus irgendwelchen Büchern 
Satzfetzen zusammenkopiert....

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren