Forum: PC-Programmierung Thread beenden in Java


von Ahnungsloser (Gast)


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!

von Kaj (Gast)


Lesenswert?


von Boris O. (bohnsorg) Benutzerseite


Lesenswert?

Das Innenleben des Threads ist wichtig. Wenn da in der run-Methode 
steht:

while(true) {
  try {
    int i++;
  } catch (Exception ex) {
  }
}

Läuft das natürlich immer. Die InterruptedException, ausgelöst durch 
Thread.interrupt, wird einfach verschluckt und es gibt keinen Grund, 
warum die run-Methode zum Ende kommen sollte.

von Ahnungsloser (Gast)


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!

von Der Andere (Gast)


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.

von Basti (Gast)


Lesenswert?

Nicht die while schleife ist das Problem, sondern der try/catch block. 
Der fängt die Exception ab/weg, die den Thread sonst beenden würde.

von Der Andere (Gast)


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
}

von Der Andere (Gast)


Lesenswert?

Basti schrieb:
> Nicht die while schleife ist das Problem, sondern der try/catch block.
> Der fängt die Exception ab/weg, die den Thread sonst beenden würde.

Das ist trotzdem die Brachialmethode mit der Brechstange.

von Der Andere (Gast)


Lesenswert?


von Ahnungsloser (Gast)


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!

von Der Andere (Gast)


Lesenswert?

Ahnungsloser schrieb:
> Jetzt müsste ich aber ja ein Objekt von "Failure_Msg_Thread" erzeugen,
> um auf die Boolean-Variable zuzugreifen.

Was denkst du machst du mit:

Ahnungsloser schrieb:
> new Failure_Msg_Thread(...)

Also schreib das halt in zwei Zeilen und merk dir das Objekt.

von c.m. (Gast)


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 :/

von Der Andere (Gast)


Lesenswert?

c.m. schrieb:
> du machst eine liste mit thread objekten

Er hat EINEN zusätzlichen Thread.

von Ahnungsloser (Gast)


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?

von Der Andere (Gast)


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.

von Der Andere (Gast)


Lesenswert?

Ach Mist muss natürlich heissen:

FailureMsgThread failureHandling = new FailureMsgThread(...);

heissen, sonst kommst du nicht an die spezifischen Methoden der 
abgeleiteten Klasse.

von Ahnungsloser (Gast)


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?!

von Jay (Gast)


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
}

von Der Andere (Gast)


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

von Ahnungsloser (Gast)


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 :(

von Jay (Gast)


Lesenswert?

Der Andere schrieb:
> Macht nur Sinn, wenn man mit Threads Berechnungen parallelsieren will
> und die Ergebnisse braucht.

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

von Der Andere (Gast)


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.

von Jay (Gast)


Lesenswert?

Der Andere schrieb:
> Dein Problem ist hier eher das verstehende Lesen :-)

Dein Problem ist, dass du ein Arsch bist.

> Sorry, aber ich muss jetzt mal wieder was arbeiten.

Ah, jetzt verschwinden, nachdem du alle Weggebissen hast. Sehr 
sympathisch.

von Ahnungsloser (Gast)


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!

von foo (Gast)


Lesenswert?

Ahnungsloser schrieb:
> private JLabel overvoltage;

Achso, es geht um Swing!
Das hättest du auch gleich sagen können.
http://www.javacreed.com/swing-worker-example/

von Ahnungsloser (Gast)


Lesenswert?

SwingWorker? noch nie gehört.


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

von foo (Gast)


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

von Ahnungsloser (Gast)


Lesenswert?

Ok..dann werde ich mich heute Abend entsprechend einlesen und bedanke 
mich schonmal für das Stichwort! :)

Ich melde mich, falls Probleme auftreten.

Grüße u. Danke!

von Der Andere (Gast)


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).

von Foobar (Gast)


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
  }

von markus (Gast)


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.

von Ahnungsloser (Gast)


Lesenswert?

Also ich versuche es jetzt mal mit dem SwingWorker..Gruß

von Ahnungsloser (Gast)


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.

von Ahnungsloser (Gast)


Lesenswert?

Ok, habe es jetzt behoben, der Thread läuft bereits.
Jetzt gilt es ihn nur noch zu beenden!

Melde mich, ob es klappt! :)

von Mladen G. (Gast)


Lesenswert?

Ist immer noch falsch..

public volatile boolean stopThread;


Waere auch besser einen Setter zu nutzen.

von Ahnungsloser (Gast)


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ß

von foo (Gast)


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.

von foo (Gast)


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()){

von Ahnungsloser (Gast)


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..

von Ahnungsloser (Gast)


Lesenswert?

der eine Button muss "btn_StartRC" heißen...sch*** copy&paste.
In meinem Programm stimmt das schon.

von foo (Gast)


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
}

von Ahnungsloser (Gast)


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

von Ahnungsloser (Gast)


Lesenswert?

Kann es daran liegen, dass ich in "DoInBackground" mit Anweisungen 
arbeiten, die exceptions benötigen?
(Öffne darin einen Socket u. diverse Input/Outputstreams)?

von Ahnungsloser (Gast)


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ß

von foo (Gast)


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.

von Ahnungsloser (Gast)


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?!

von Foobar (Gast)


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..

von Ahnungsloser (Gast)


Lesenswert?

Ahh, das leuchtet ein! Danke!

von foo (Gast)


Lesenswert?

Wenn du dann das mit den Exceptions (incl. aussagekräftigen 
Fehlermeldungen und sauberen exits) ausprogrammiert hast, kannst ja auch 
mal noch so eine Verriegelung wie in meinem Beispiel einbaun.
Weil: http://imgur.com/vRF9b47

von Der Andere (Gast)


Lesenswert?

Foobar schrieb:
> Du solltest mal an den Grundlagen arbeiten..

Warum nur kommt mir der Satz bekannt vor...

von Läubi .. (laeubi) Benutzerseite


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....

von Markus (Gast)


Lesenswert?

Läubi .. schrieb:
> Programmieren ist doch keine Quizshow wo man sich
> munter von Frage zu frage "rät" und im Zweifle den Foren-Joker befragt.
Jetzt weiß er aber wenigsten, was Backtracking ist, aber nicht, daß man 
das nicht für die Entwicklung verwendet.

von 27hdec (Gast)


Lesenswert?

Einfach return;

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.