Api mit eine Methode die "immer" läuft bis "stop" "gerufen wird.

dermoritz

Bekanntes Mitglied
Ich baue gerade an einer Klasse ide ungefähr so aussieht (Pseudocode):

Java:
public class Klasse{

private boolean stop=false;

public TuWas(){
 stop=false;
 while(!stop){
  ...
}

}

public void setStop(boolean stop){
 this.stop=stop
}
}

Also die Klasse bietet eine Methode die solange laufen soll bis man sagt sie soll anhalten (dann soll der aktuelle Schleifendurchlauf noch beendet werden). Mein Code funktioniert natürlich nicht. Nun frage ich mich ganz unvoreingenommen: wie macht man so was.

(Wenn ich etwas voreingenommen Fragen würde, würde ich Begriffe wie "Thread" oder "Runnable" auspacken. Aber ich bin mir eben nicht sicher ob und wie das gehen könnte bzw. was vernünftig ist)
 
Gegenfrage - Was läuft nicht? ... weil genau so mache ich das auch immer - und es funktioniert ... ich habe die leichte vermutung das Du keinen Thread gestartet hast ... mach Dich mal über Thread schlau
 
soll er anhalten und ggf. weiterlaufen oder komplett anhalten? ersteres würd ich mit einem lockobject und einem boolean machen, und einfach den boolean in run abprüfen und das obj.wait() aufrufen. komplett anhalten würde ich den thread interrupten und in der run abprüfen, ob er unterbrochen wurde.

das sind 2 unterschiedliche status. beim einem wait (reaktivierbar) beim anderen stop (ende)
 
Danke,

aus euren Antworten schließe ich dass man einen extra Thread braucht?! Mein Code läuft natürlich deshalb nicht, da tuWas() ewig läuft und solange das läuft kann man ja keine andere Methode aufrufen oder?

Diese Methode mit der "ewigen" while Schleife soll solange laufen bis bestimmte Kriterien erfüllt sind. Diese Kriterien sind beim Start definitiv nicht erfüllt.
Das ändern der Kriterien soll über andere Methoden laufen (setStop).

die frage ist wie man das realisiert (ob mit Thread oder ohne?!) - ich hätte alles gerne in einer Klasse die eben eine einfache Api hat: starte(), stoppe()
 
hier ein Beispiel zu Thread:

Java:
import java.io.*;

public class Test extends Thread {

	private boolean pause = false;
	private Object obj = new Object();

	public static void main(String[] args) throws IOException, InterruptedException {
		Test t = new Test();
		t.start();
		Thread.sleep(1000);
		t.pause();
		System.out.println("leg dich schlafen");
		Thread.sleep(2000);
		t.weiter();
		System.out.println("arbeite weiter!!!!");
		Thread.sleep(1000);
		t.interrupt();
		System.out.println("feierabend");
	}

	public void pause() {
		this.pause = true;
	}

	public void weiter() {
		this.pause = false;
		synchronized (obj) {
			this.obj.notify();
		}
	}

	public void run() {
		int i = 0;
		synchronized (obj) {
			while (true) {
				System.out.println(i++);
				try {
					if (pause) {
						obj.wait();
					} else {
						Thread.sleep(100);
					}
				} catch (InterruptedException e) {
					break;  // ENDE
				}
			}
		}
	}
}[/Java]
 
Danke für den Code,

funktioniert der Thread auch als innere Klasse? Also mein Klasse soll wie gesagt ein ganz einfache Api haben und man soll nix davon merken das innerhalb, eine bestimmte Methode in einem extra Thread läuft.

Geht das ganze auch mit "runnable" (Das verwendet man doch in gui's in ähnlichen Fällen?!)
-- weil ich mir da so unsicher bin: ob thread oder runnable oder was ganz anderes wollte ich ganz unvoreingenommen ran.

Also am liebsten hätte ich wie beschrieben eine simple Methode start(). die vollständig die thread/runnable-Klasse kapselt, die run() methode definiert und auch ausführt.

und stop() sollam liebsten einfach ein flag setzen der innerhalb run() bzw innerhlab der while-Schleife geprüft wird.
 
Zuletzt bearbeitet:
funktioniert der Thread auch als innere Klasse? Also mein Klasse soll wie gesagt ein ganz einfache Api haben und man soll nix davon merken das innerhalb, eine bestimmte Methode in einem extra Thread läuft.
Ja
Geht das ganze auch mit "runnable" (Das verwendet man doch in gui's in ähnlichen Fällen?!)
Man sollte auch eher Runnable implementieren ans statt von Thread zu erben.
Also am liebsten hätte ich wie beschrieben eine simple Methode start(). die vollständig die thread/runnable-Klasse kapselt, die run() methode definiert und auch ausführt.

und stop() sollam liebsten einfach ein flag setzen der innerhalb run() bzw innerhlab der while-Schleife geprüft wird.
Kann man so machen.
 
dann mal frei aus der Hüfte geschossen:

Java:
public class Klasse{
private boolean stoppe=false;
public stoppe(){
 stoppe=true;
}
public final void starteProzess() {
		stoppe = false;
		new Runnable() {
			@Override
			public void run() {
				while (!stoppe) {
					
				}
				return;
			}
		} .run();
	}
}

funktioniert das so wie ich es will? (ich hoffe alle wissen was ich will ;-))
 
funktioniert das so wie ich es will? (ich hoffe alle wissen was ich will ;-))
Wirst es hoffentlich selbst gemerkt haben: Nein
Java:
public class Klasse {
    private boolean stoppe=false;

    public stoppe(){
        stoppe=true;
    }

    public final void starteProzess() {
        stoppe = false;
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (!stoppe) {
                    
                }
            }
        }).start();
    }
}
 
Java:
 private boolean stoppe=false;
sollte eigentlich
Java:
 private volatile boolean stoppe=false;
lauten.
 
danke für den Hinweis maki. Ich hab kurz gegoogelt und was ich verstanden hab ist volatile speziell für Variablen über die sich threads unterhalten?! - also genau das was bei mir passiert

Zum besseren Verständnis:
Was passiert ohne volatile, im Allgemeinen und speziell in meinem Beispiel.

Ein Kollege macht mich gerade darauf Aufmerksam (und in der Java insel ist auch ein entsprechendes Beispiel):

warum könnte das:
Java:
...
new Thread(new Runnable() {
			@Override
			public void run() {
				logger.log(Level.INFO, "Übergabeprozess gestartet.");
				while (!stoppe) {

				}
				logger.log(Level.INFO, "Übergabeprozess gestoppt.");
				return;
			}
		}).start();

...
besser sein??
 
Zuletzt bearbeitet:
Zum besseren Verständnis:
Was passiert ohne volatile, im Allgemeinen und speziell in meinem Beispiel.
Ohne volatile ist nicht garantiert, dass der eine Thread die Änderung des anderen Threads "sieht".
D.h. konkret, dein Thread könnte u.U. nie mitbekommen dass stop auf true gesetzt wurde.

Das ist natürlich vereinfacht dargestellt, zu volitale/concurrency gibt es noch viel mehr, Angelika Langer schreibt imho sehr gute Artikel darüber: AngelikaLanger.com - Effective Java - A column by Angelika Langer & Klaus Kreft - Angelika Langer Training/Consulting
(Ab 2008)
 
Danke ihr seid alle so schnell: ich hab oben was geändert anstatt

new runnable(){}.run kann man auch new thread(new runnable...).start(); machen. wo ist da der Unterschied? (letztere macht Die Javainsel so und ein Kollege meint das sei aus irgendeinem Grund besser)

@Fart:deine Anmerkung betrifft die eigentliche Frage dieses Threads: ich wollte eigentlich gar nicht gleich mit Threads rummachen sondern eine Vorgehensweise für mein Problem. Aber alle antworten deuteten sofort auf "Thread". Falls es eine bessere "Best Practice" für mein Problem gibt: immer her damit
 
Zuletzt bearbeitet:
@Fart:deine Anmerkung betrifft die eigentliche Frage dieses Threads
Ja, weil ich denke, dass man heutzutage vieles nicht mehr selber über Threads lösen muss...

Her damit gab es schon: stöber mal die Links durch, die ich gepostet habe. Es ist immer gut zu wissen was es gibt bevor man was braucht...
 
Zuletzt bearbeitet:
so nun hab ich mal das concurency Kapitel überflogen - speziell den "high level"-Kram (java.util.concurrent). Für meinen speziellen Fall sehe ich da keinen Vorteil anstatt (new Thread(r)).start(); (Mich interessiert nach wie vor der Unterschied zu new runable(){}.run()) würde man eben e.execute(r) verwenden (Executor Interfaces (The Java™ Tutorials > Essential Classes > Concurrency)).

Wenn ich es richtig verstehe hat man mit dem Executor bessere Möglichkeiten das Ausführen des Threads zu steuern. In meinem Fall will ich aber genau den sofortigen Start. Und da würde sich e.execute() identsiche verhalten , oder?
 
Zuletzt bearbeitet:
Mhm, ich hab ein Problem. FindBugs hat mich gerade darauf hingewiesen: innerhalb des Threads werden alle Ausnahemn verschluckt - das ist blöd.
Ein ähnliches Problem hatte ich mal mit "swingWorker" - dort gab es aber die get() Methode und über ihre "ExecutionException" kam man an alle Exceptions ran. Gibt es was ähnliches für Threads?

In diesem Zusammenhang ist mir aufgefallen, dass quasi meine ganze Programmlogik in diesem Thread abläuft und damit werden ja sämtliche Exeptions "komisch"/ gar nicht behandelt. -Ich zweifele gerade an der Kalssenarchitektur.
- sind diese Zweifel berechtigt?

Nun hätte ich da 2 Ideen:
1. ich drehe die Rollen der Threads um: Mein starteProcess() läuft im Mainthread und mein stoppe() macht den anderen Thread auf. Das blöde ist stoppe() kann ich nicht starten nachdem starteProcess() gestartet ist - das läuft ja ewig. Also müsste man diesen stoppeThread unmittelbar beim starten von starteProcess() starten?! (ich würde alse gerne während methoden (startProzess) laufen eine Variable(stoppe) ändern)
Nun ist aber die Preisfrage (wenn das obige für irgendwen Sinn ergibt), wie ich über den stoppeThread eine variable (stoppe) setze.

2. Ich arbeite nicht mit einer inneren Klasse, sondern baue ein "richtige" Klasse die runnable implementiert. Das würde zumindest etwas die Struktur verbessern. - das Problem mit den Exceptions hätte ich hier weiterhin.
 
Zuletzt bearbeitet:
Wenn ich es richtig verstehe hat man mit dem Executor bessere Möglichkeiten das Ausführen des Threads zu steuern. In meinem Fall will ich aber genau den sofortigen Start. Und da würde sich e.execute() identsiche verhalten , oder?

Praktisch, oder?
Wie du anhand der obigen Diskussion erahnen kannst, ist die Programmierung mit Threads nur auf den ersten Blick trivial. Diese Services kapseln viel von der Komplexität, sind somit in der Handhabung einfacher und lassen den Anwender weniger Fehler machen. Und da haben wir auch schon den Vorteil.
 
(new Thread(r)).start(); (Mich interessiert nach wie vor der Unterschied zu new runable(){}.run())

Thread ist eine Klasse.
Runnable ist ein Interface.

Eine Klasse kann mehrere Interface implementieren, aber nur von einer anderen Klasse erben.
Erbst du von Thread, verbaust du dir die Möglichkeit von einer "Sinnvolleren" Klasse zu erben.

Die Klasse Thread besitzt intern Logik, die Nebenläufigkeit erst ermöglicht.

mit der Methode start() wird eben diese Logik gestartet. In der Methode run() steht drin was eben Ausgeführt werden soll.

Um nun auf Runnable zu kommen. Runnable ist ein Interface, das dafür sorgt das eine run Methode vorhanden ist. Mit Runnable wird ein Runnable-Objekt an Thread übergeben. Wird der Thread nun gestartet, ruft er seine RunMethode auf, oder die von dem übergebenen Runnable Objekt.

Die Klasse Thread kann man sich etwa so vorstellen (stark vereinfacht)
Java:
class Thread implements Runnable{
  Runnable runnable=null;

  public void start(){
    starteEinenNeuenProzezz();//das ist die Logik
    run();
  }
//Run wird beim Vererben, normalerweise überschrieben.
  public void run(){
    if(runnable!=null){
     runnable.run();
    }
  }
}

Wenn du allerdings die Methode run() direkt auf Runnable oder Thread aufrufst, dann wird die Methode ausgeführt wie jede andere Methode auch. Die Logik das das Nebenläufig ist steckt in start() und wird nur aufgerufen wenn der Thread über start() gestartet wird.
 
Zuletzt bearbeitet von einem Moderator:
Danke fart - dann werd' ich mir das wohl mal genauer anschauen.

Wie weiter oben beschrieben werde ich den Thread eigentlich die Hauptfunktionalität der Klasse ausführen. Irgendwie habe ich ein ungutes Gefühl innerhalb des Threads Methoden der äußeren Klasse Aufzurufen.
wie oben (http://www.java-forum.org/allgemein...ode-immer-laeuft-stop-gerufen.html#post695924) beschrieben hätte ich da 2 mögliche Ideen (das was ich über Exceptions schreibe ist glaube Müll - ichhab findBugs mißverstanden).
Da würde mich interessieren ob eine von diesen Ideen Sinn macht und eventuell besser leichter mit java.util.concurrency besser Lösbar ist.

@JohannisderKaeufer
heißt das, das es ohne "thread" und start() gar keinen Sinn macht? Bzw. das falls man nur runnable.run() ausführt das identisch ist mit einem normalen Methodenaufruf?
 
Zuletzt bearbeitet:
heißt das, das es ohne "thread" und start() gar keinen Sinn macht? Bzw. das falls man nur runnable.run() ausführt das identisch ist mit einem normalen Methodenaufruf?
Ja. run() ist eine normale durch Runnable implementierte Methode, ergo ist ein direkter Aufruf dieser Methode nicht nur identisch mit einem normalen Methodenaufruf, es ist sogar ein normaler Methodenaufruf ;-) Während in der start() des Threads noch ein nativer Methodenaufruf ist, der einen neuen Prozess startet.
 
Genau.
Laß folgendes mal in laufen. Einfach in eine main Methode packen.
Java:
Runnable runnable = new Runnable(){
  public void run(){
    for(int i = 0; i<1000;i++){
      System.out.println(""+i);
    }
  }
};

new Thread(runnable).run();
System.err.println("Thread mit Run gestartet");

new Thread(runnable).start();
System.err.println("Thread mit Start gestartet");

Ergebnis wird in etwa so aussehen.
Code:
1
...
999
Thread mit Run gestartet
1
2
3
Thread mit Start gestartet
4
5
...
999

Ansonsten aus den 1000 vielleicht 10000 oder 100000 machen, damit es deutlicher wird.
 
mal ne andere Frage in diesem Zusammenhang: Wie debugge ich diesen Thread bzw die Methode die intern einen neuen Thread aufmacht?
Ich benutze Eclipse und da kann ich mich auf den Kopf stellen, aber innerhalb der Run-Methode krieg ich keinen funktionierenden Breakpoint rein.
In der Liste unter "RemoteTestrunner" seh ich den thread auch nicht. Dort gibts nur "[main]" und einen "[ReaderThread]".
 
Breakpoint setzen sollte reichen, unter den Breakpoint einstellungen kannst du dann noch konfigurieren ob die gesamte VM angehalten werden soll oder nur der eine Trhead (default).

Wichtig ist eben dass du nie dir run Methode direkt aufrufst, sondern über start den Thread startest.
 

Zurück
Oben