Threads

  • Themenstarter Themenstarter Heidii
  • Beginndatum Beginndatum
H

Heidii

Gast
Hallo,

um mich mit dem Thema Threads zu befassen habe ich ein kleines Programm mit einem JButton (Start) geschrieben.

Gewünschte Funktion:
Erstes Mal auf den Button klicken:
der Text Start auf dem Button wird auf Beenden gewechselt.
Pro Sekunde wird ein Text ausgegeben.

Zweites Mal auf den Button klicken:
der Text Beenden auf dem Button wird auf Start gewechselt.
Die Textausgabe wird beendet.

Drittes Mal auf den Button klicken:
Alles beginnt wieder von vorne.

Hier mein Code (Auszug), der Fensterklasse mit dem JButton:
Java:
// Im Konstruktor lege ich eine Instanz vom Thread an:
Faden MFaden = new Faden();

	private class TheEvent implements ActionListener{

	
		public void actionPerformed(ActionEvent e) {
			
			if(pushed==false){
				Knopf1.setText("Beenden");
			        pushed = true;
				MFaden.start();
			}
			else{
				Knopf1.setText("Start");
				pushed = false;
			        MFaden.interrupt();				
			}			
		}
	}

Hier mein Code (Auszug) der Thread Klasse:
Java:
	public void run(){
		while(this.isInterrupted()==false){
		System.out.println("TEST");
		
		try {
			sleep(1000);
		} catch (InterruptedException e) {
			return;
		}	
	}
}

Folgendes ist das Problem: Wenn ich den Button einmal klicke funktioniert alles wie gewünscht. Auch wenn ich 2 Mal klicke funktioniert alles nach Plan.
Wenn ich ein 3tes mal klicke, dann sollte ich doch den Thread wieder von vorne starten, dies funktioniert aber nicht und ich kriege vom Compiler folgende Meldung:
Exception in thread "AWT-EventQueue-0

Ich denke ich starte den Thread korrekt, aber ich beende ihn irgendwie nicht richtig und aus diesem Grund kann ich ihn nicht neu starten.

Kann mir jemand sagen ob dies richtig ist, bzw. was die Compilermeldung zu bedeuten hat, bzw. was ich anpassen muss. Vielen Dank für alle Tipps schon jetzt.

Heidii
 
also mit Thread.interrupt() einen thread von außen gewaltsam killen solltest du dir gar nicht erst angeöhnen ... das ist ganz schlechter stil und kann bei komplexen projekten zu großen problemen führen ...

deutlich besser wäre es wenn du ein flag nutzt auf welches im loop geprüft wird .. und welches von außen durch einen setter getoggled werden kann ... außerdem sollte man nicht mit return; aus run() aussteigen ... zumindest nicht ohne vorher sauber alles aufgeräumt zu haben ...


zum eigentlichen problem

so wie es aussieht hast du genau EIN thread objekt was EINMAL mit "new" erzeugt wurde ... und dieser wird auch genau ein mal gestartet ... und danach (gewaltsam) beendet ... und fertig ...

ein Thread hat folgenden lebenszyklus :

- created
- inited
- started
- RUNNING
- termianted

wenn ein thread TERMINATED erreicht hat ist er zu ende ... der thread ist durch ... also kann er nicht noch mal mit start() gestartet werden ...

du müsstest also eher sowas bauen

1ter klick : neuen thread erzeugen und temporär speichern ... > start()
2ter klick : thread sauber durch ein flag runterfahren ... nach stop (kann mit .wait() oder nem callback gemacht werden) alles aufräumen und die referenz auf NULL setzen ...
damit gibt man das objekt wieder frei und es kann vom GC aufgeräumt werden ...
3ter klick : wieder von vorne neuen thread erzeugen ...
 
Hallo tröööt,

vielen Dank für deine Antwort! Werds gleich probieren.

Liebe Grüsse
Heidii
 
Also einen Thread mit "interrupt()" in den Selbstmord treiben ist die einzige Möglichkeit einen solchen vorzeitig abzubrechen. Schlechter Stil ist es, sie mit "stop()" gewaltsam zu töten (evtl. beziehen jetzt einige User mehr die Signatur eines Users nicht mehr unbedingt auf Foren-Threads 😉). Schlechter Stil ist es auch Threads mit Running-Flags zu zukleistern, das kann man sich für Runnables aufheben.
Aber mal am rande: Was du da machen willst, ist doch eigentlich nur 'ne Toggle-Funktion (obwohl mir dann der Sinn für den 3. Klick entfleucht). Wofür benötigst du da einen Thread?
BTW.: Wenn man innerhalb der "run()"-Methode eines Threads eine InterruptedException fängt (bzw. fangen muss), sollte man "interrupt()" an diesen Thread weitergeben (bedeutet: im Catch-Block "this.interrupt()" aufrufen).

Ach ja... Objekte, die von einem bereits toten Objekt referenziert werden sterben mit diesem Objekt, sofern es die letzte Referenz davon war. Dieses Nullsetzen ist ein Relikt aus den Zeiten, wo "finalize()" noch brauchbar erschien. Der aktuelle GC benötigt diese Aufmerksamkeit nicht mehr, so dass man sich das Nullsetzen sparen kann.

Und noch was ganz wichtiges: Threads, die einmal gelaufen sind, können nicht erneut gestartet werden, dazu benötigt man eine neue Instanz.
 
Zuletzt bearbeitet von einem Moderator:
Wobei ich ehrlich gesagt (auch nach vielen Jahren mit Verwendung von Threads) noch nie ganz kapiert hab, wozu es interrupt() gibt, da auch hier ja ein Flag gecheckt werden muss (interrupted()). Die Vorgehensweise mit dem eigenen volatile-Flag stand zumindest früher mal auch in Lehrbüchern drin.

Also hat man dann z.B. die Konstruktion
Code:
 while (!interrupted() && ownFlag) {}

Bisher bin ich immer ohne interrupt() ausgekommen. Kann natürlich dennoch sein, dass ich was übersehe, die Threadsachen sind nicht sonderlich intuitiv.

Olli
 
Java:
			if(pushed==false){
				Knopf1.setText("Beenden");
			}
			else{
				Knopf1.setText("Start");
			}
Java:
		while(this.isInterrupted()==false){
Zu allen Thread-Kommentaren hier noch ein Stil-Kommentar.
Pfui!
Man vergleicht booleans nicht nochmal mit booleans um dann einen neuen boolean zu bekommen.

Für das erste beispiel gibt es 2 möglichkeiten:
Java:
			if(! pushed){
				Knopf1.setText("Beenden");
			}
			else{
				Knopf1.setText("Start");
			}
Java:
			if(pushed){
				Knopf1.setText("Start");
			}
			else{
				Knopf1.setText("Beenden");
			}
fürs zweite:
Java:
		while(! this.isInterrupted()){
 
Dafür ist:
Java:
while(this.isInterrupted()==false){
Für Anfänger und auch Fortgeschrittene leichter zu lesen!
Ein '!' kann man übersehen, bei einem '==false' ist das schon schwerer!
 
Dafür ist:
Java:
while(this.isInterrupted()==false){
Für Anfänger und auch Fortgeschrittene leichter zu lesen!
Ein '!' kann man übersehen, bei einem '==false' ist das schon schwerer!
...und in Java die einzige Möglichkeit den Semantic-Error No.1 zu produzieren... [c]while(n=true) { // do stuff };[/c]
 

Zurück
Oben