Thread mit Pausefunktion

Status
Nicht offen für weitere Antworten.

noobler

Mitglied
Ich wollte einen Thread programmieren der von einem anderen Thread aus jederzeit pausiert, wieder aufgeweckt und beendet werden kann. Unten ist das bescheidene Ergebnis zu sehen. Nun zur Frage ob der Code für die beschriebene Aufgabe geeignet ist. Also gibt es problematische Stellen wegen Threadsicherheit oä., kann man das ganze evtl. besser machen?

Java:
public class MyThread extends Thread {

    private boolean stopRequested;
    private boolean suspendRequested;
    
    public MyThread() {
		stopRequested = false;
		suspendRequested = false;
		start();
    }
    
    public synchronized void requestStop() {
        stopRequested = true;
        notify();
    }
    
    public synchronized void requestSuspend() {
        suspendRequested = true;
    }
    
    public synchronized void requestWake() {
        suspendRequested = false;
        notify();
    }
    
    private synchronized boolean continueThread() {
        while(!stopRequested && suspendRequested) {
            try {
                wait();
            }
            catch(InterruptedException e) {
                // check flags again
            }
        }
        return !stopRequested;
    }
    
    @Override
    public void run() {
        while(continueThread()) {
            // do stuff
        }
    }
}
 
S

SlaterB

Gast
finde ich gut, Zeile 7 + 8 braucht man nicht, sonst wüßte ich erstmal nix zu ändern

requestSuspend() müsste evtl. nichteinmal synchronisiert sein, bei boolean sehe ich nichts, was schiefgehen kann,
die anderen Methoden brauchen das allein schon für wait + notify
 

Marco13

Top Contributor
Hui, ich komme gerade von Angelika Langer's Seiten zu "volatile & Co" - ich würde das synchronized NICHT weglassen :D :oops:
 

Ebenius

Top Contributor
Ich würde nicht gegen [c]this[/c] sondern gegen einen privaten Member synchronisieren; wait/notify entsprechend. Falls Du das aus einem bestimmten Grund nicht willst, solltest Du notifyAll() statt notify() rufen.

Zeile 32 würde ich ersetzen: [java=32]interrupt(); // check flag again
break;[/code]

Zeile 40 entsprechend: [java=40] while(continueThread() && !isInterrupted()) {[/code]

Ansonsten find ichs auch gut.

Ebenius
 

noobler

Mitglied
Viele dank für eure Hilfe! Ich habe mal versucht eure Verbesserungsvorschläge umzusetzen:

Java:
public class MyThread extends Thread {

	private Object monitor;
    private boolean stopRequested;
    private boolean suspendRequested;
    
    public MyThread() {
		monitor = new Object();
		start();
    }
    
    public void requestStop() {
		synchronized(monitor) {
			stopRequested = true;
			notifyAll();
		}
    }
    
    public void requestSuspend() {
		synchronized(monitor) {
			suspendRequested = true;
		}
    }
    
    public void requestWake() {
		synchronized(monitor) {
			suspendRequested = false;
			notifyAll();
		}
    }
    
    private boolean continueThread() {
		synchronized(monitor) {
			while(!stopRequested && suspendRequested) {
				try {
					wait();
				}
				catch(InterruptedException e) {
					interrupt(); // check flag again
					break;
				}
			}
			return !stopRequested;
		}
    }
    
    @Override
    public void run() {
        while(continueThread() && !isInterrupted()) {
            //do stuff
        }
    }
}
Leider hapert es jetzt mit dem Verständnis.
1. War "gegen einen privaten Member synchronisieren" so gemeint?
2. Welchen Vorteil hat das Synchronisieren gegen einen privaten Member?
3. Die Änderungen mit interrupt() und isInterrupted() dienen dazu den Thread zusätzlich von "aussen" durch interrupt() beenden zu können, oder? Wenn der Thread in wait() hängt und von aussen requestWake() aufgerufen wird, wird dann nicht auch jedesmal eine Exception erzeugt, die dazu führen würde, dass der Thread durch den aufruf von requestWake() beendet wird?
4. "Volatile" hab ich so gar nicht verstanden. Was hätte die Verwendung von Volatile für Vorteile? Und könntest du das an einer Methode konkretisieren?
 

Ebenius

Top Contributor
Alle notifyAll()-Aufrufe müssen nun [c]monitor.notifyAll()[/c] heißen; alle wait()-Aufrufe entsprechend [c]monitor.wait()[/c] entsprechend.

1. War "gegen einen privaten Member synchronisieren" so gemeint?
2. Welchen Vorteil hat das Synchronisieren gegen einen privaten Member?
1. Ja, 2. Da Du den Thread wiederverwendbar implementierst, kann jeder andere von außen auch auf die Thread-Variable synchronisieren, darauf warten, etc. und dem Mechanismus so ins Handwerk pfuschen. Wenn Du synchron zu einem separaten Monitor arbeitest kannst Du diese Fehlermöglichkeit von vorn herein ausschließen.

3. Die Änderungen mit interrupt() und isInterrupted() dienen dazu den Thread zusätzlich von "aussen" durch interrupt() beenden zu können, oder?
Es ging mir nicht darum, zu ermöglichen, den Thread auch von außen über interrupt zu beenden. Es geht mir eher darum, dass Thread nunmal die interrupt-Methode hat und MyThread diese erbt. Daher sollte das Verhalten auch dem Erwarteten Verhalten eines 08/15-Thread entsprechen.

Wenn der Thread in wait() hängt und von aussen requestWake() aufgerufen wird, wird dann nicht auch jedesmal eine Exception erzeugt, die dazu führen würde, dass der Thread durch den aufruf von requestWake() beendet wird?
Verstehe ich nicht.

4. "Volatile" hab ich so gar nicht verstanden. Was hätte die Verwendung von Volatile für Vorteile? Und könntest du das an einer Methode konkretisieren?
Meiner Meinung nach keine Vorteile, da Du ohnehin synchron arbeitest und arbeiten solltest.

Den Monitor würde ich noch [c]final[/c] machen; weil's besser ist.

notifyAll() musst Du nicht benutzen, kannst Du aber. Das musst (solltest) Du nur machen, wenn Du riskieren musst, dass mehere Threads auf den Monitor warten. Da Dein Monitor nun von außen nicht mehr erreichbar ist, ist sicher gestellt, dass das nicht passiert.

Ebenius
 

javimka

Top Contributor
Wenn du einen internes Lock-Objekt monitor hast, dann muss du auch auf diesen wait() und notifyAll() aufrufen. Also [c]monitor.wait()[/c].

Variabeln, die als volatile deklariert wurden, sind für alle laufenden Threads "gleich". Zurecht fragst du dich, wann sie denn nicht gleich sind. Der Computer verfügt über zig-Zwischenspeicher, in denen dein boolean gespeichert ist. Der Wert wird dabei aus dem RAM in einen Cache gespeichert, wenn er oft verwendet wird. Aber nicht alle Threads müssen zwingend mit derselben Kopie arbeiten. Es kann passieren, dass ein Thread "seine" Kopie der boolean auf true stellt, ein anderer Thread aber eine andere Kopie verwendet, die von dem zunächst nichts mitkriegt. Natürlich wird im praktischen Gebrauch früher oder später jeder Thread, der diese boolean liesst, die Veränderung sehen, aber theoretisch kann das auch eine lange Zeit dauern. Wenn du sie aber als volatile deklarierst, ist jeder Thread gezwungen, zu jedem Zeitpuntk den echten Wert der Variable zu verwenden. Konkret wird die Variable dann stets aus dem RAM gelesen, so wird jeder schreibende Zugriff sofort von allen Threads wahrgenommen.

Sieht dann so aus:
Java:
    private volatile boolean stopRequested;
    private volatile boolean suspendRequested;
 

Ebenius

Top Contributor
Sieht dann so aus:
Java:
    private volatile boolean stopRequested;
    private volatile boolean suspendRequested;
Nur damit's nicht unter geht; da alle Zugriffe synchronisiert sind, trifft dieser Zustand nie auf und daher sollten die Variablen auch nicht [c]volatile[/c] deklariert sein.

Ebenius
 

noobler

Mitglied
Hier nochmal der überarbeitete Code. Falls noch jemand einen Verbesserungsvorschlag oder eine elegantere Lösung für das selbe Problem hat, darf das kommentiert werden.
Java:
public class MyThread extends Thread {

    private final Object monitor;
    private boolean stopRequested;
    private boolean suspendRequested;
    
    public MyThread() {
        monitor = new Object();
        start();
    }
    
    public void requestStop() {
        synchronized(monitor) {
            stopRequested = true;
            monitor.notify();
        }
    }
    
    public void requestSuspend() {
        synchronized(monitor) {
            suspendRequested = true;
        }
    }
    
    public void requestWake() {
        synchronized(monitor) {
            suspendRequested = false;
            monitor.notify();
        }
    }
    
    private boolean continueThread() {
        synchronized(monitor) {
            while(!stopRequested && suspendRequested) {
                try {
                    monitor.wait();
                }
                catch(InterruptedException e) {
                    interrupt();
                    break;
                }
            }
            return !stopRequested;
        }
    }
    
    @Override
    public void run() {
        while(continueThread() && !isInterrupted()) {
            //do stuff
        }
    }
}
Zu 2.: Ich hab das ein paar mal getested, läuft augenscheinlich so wie beabsichtigt. Der Thread lässt sich mit interrupt() und requestStop() beenden. Also vielen Dank soweit.

Allerdings hab ich noch eine kleine Frage:
Wenn ich in der Hauptschleife wie folgt wait(1000) benutze bekomme ich eine "llegalMonitorStateException".
Java:
while(continueThread() && !isInterrupted()) {
	try {
		wait(1000);
		System.out.println("working");
	}
	catch(Exception e) {
		e.printStackTrace();
	}
}
Benutze ich stattdessen sleep(1000) verhält es sich wie erwartet.
Java:
while(continueThread() && !isInterrupted()) {
	try {
		sleep(1000);
		System.out.println("working");
	}
	catch(Exception e) {
		e.printStackTrace();
	}
}
Woran liegt das?
Und letztlich nochmal zum Thema volatile:
Wenn ich den Zugriff auf die Flags synchronisiere hat es doch den gleichen Effekt wie volatile?
Ist volatile dann nur eine verkürzte Schreibweise?
Man deklariert einfach ein Variable als volatile und kann mit beliebig vielen Threads lesend und schreibend auf sie zugreifen?
Volatile bewirkt das der lesende und schreibende Zugriff auf eine Variable tatsächlich eine atomare Operation ist?
 
Zuletzt bearbeitet:
S

SlaterB

Gast
wenn auf monitor synchronisiert wird, dann monitor.wait() + monitor.notify()
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Vorschläge für Umstellung auf Thread-Nutzung erwünscht Java Basics - Anfänger-Themen 11
Z Sikuli Thread Fehler Java Basics - Anfänger-Themen 3
Leyla Thread isInterrupt Java Basics - Anfänger-Themen 18
P Meldung aus Java-Klasse in Thread an aufrufende Klasse Java Basics - Anfänger-Themen 1
A Thread XML-Dateien zusammenfügen Java Basics - Anfänger-Themen 11
F influxdb Upload in eigenem Thread Java Basics - Anfänger-Themen 2
frager2345 Thread - Methoden synchronized deklarieren Java Basics - Anfänger-Themen 10
berserkerdq2 Größter unterschied von extends thread und implements runnable? Java Basics - Anfänger-Themen 2
T Thread beenden aus zweiter Klasse Java Basics - Anfänger-Themen 4
A Thread - Synchronized Java Basics - Anfänger-Themen 10
A Thread Producer - Consumer Java Basics - Anfänger-Themen 1
A Thread-Semhapore Java Basics - Anfänger-Themen 0
A Thread Exchanger Java Basics - Anfänger-Themen 22
A Thread-Cyclicbarrier Java Basics - Anfänger-Themen 4
B In einem Thread Endlosschleife beenden Java Basics - Anfänger-Themen 19
A Thread-Verklemmung Java Basics - Anfänger-Themen 10
A Thread-Schreibe-Lese-Problem Java Basics - Anfänger-Themen 4
A Thread find number Java Basics - Anfänger-Themen 8
F Thread.sleep() Java Basics - Anfänger-Themen 5
F Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 11 at main.main(main.java:11) Java Basics - Anfänger-Themen 2
A Thread Java Basics - Anfänger-Themen 3
M Exception in thread "main" java.util.NoSuchElementException Java Basics - Anfänger-Themen 2
A Thread Java Basics - Anfänger-Themen 8
B Compiler-Fehler Fehlermeldung Exception in thread, falsche Eingabewert Java Basics - Anfänger-Themen 2
M Thread-Zustände Java Basics - Anfänger-Themen 6
CptK For-Schleife in Thread nach jedem Durchlauf pausieren Java Basics - Anfänger-Themen 35
S Kriege Fehler "Exception in thread" beim Benutzen von SubStrings. Java Basics - Anfänger-Themen 2
B Endlosschleife Thread sauber beenden Java Basics - Anfänger-Themen 19
D Java Thread wartet nur ein mal Java Basics - Anfänger-Themen 1
D Java Thread wartet nur ein mal Java Basics - Anfänger-Themen 0
O Exception in thread "main" java.lang.ArithmeticException: / by zero Java Basics - Anfänger-Themen 4
C Thread und TimerTask, Verstädnisproblem Java Basics - Anfänger-Themen 10
amgadalghabra Sorting Thread Launcher Java Basics - Anfänger-Themen 3
B Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException Java Basics - Anfänger-Themen 8
A Thread Java Basics - Anfänger-Themen 4
A Thread Java Basics - Anfänger-Themen 1
A Thread Java Basics - Anfänger-Themen 0
R Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException Java Basics - Anfänger-Themen 5
S Compiler-Fehler Exception in thread "main" java.lang.Error: Unresolved compilation problem: Java Basics - Anfänger-Themen 6
L Liste in anderem Thread laden Java Basics - Anfänger-Themen 1
B Thread / Prozess stoppen? Java Basics - Anfänger-Themen 22
I Compiler-Fehler Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 Java Basics - Anfänger-Themen 3
B Threads Thread sleep() Method einfache Frage Java Basics - Anfänger-Themen 8
W Thread Aufgabe - Vorgehensweise Java Basics - Anfänger-Themen 8
L Liste in anderem Thread laden Java Basics - Anfänger-Themen 0
J Threads PrograssBar update während thread Java Basics - Anfänger-Themen 13
D Compiler-Fehler Wert auf Datenbank übertragen und Sleep Thread Java Basics - Anfänger-Themen 3
Spencer Reid JavaFX Memory Thread.sleep Java Basics - Anfänger-Themen 1
S Thread.sleep mit JProgressBar Java Basics - Anfänger-Themen 1
ralfb1105 Frage zu Thread Synchronisation mit wait() und notify() Java Basics - Anfänger-Themen 3
R Exception in thread "main" java.lang.NullPointerException Java Basics - Anfänger-Themen 10
J JavaFX -> SocketIO -> Thread -> Update Label Java Basics - Anfänger-Themen 13
J Thread Handling Java Basics - Anfänger-Themen 9
A Problem mit Thread.sleep Java Basics - Anfänger-Themen 4
C Thread in Methode + raus aus der Schleife Java Basics - Anfänger-Themen 10
E Threads Thread in While-Schleife nur einmal starten Java Basics - Anfänger-Themen 2
F Daten von Thread an den aufrufenden zurückgeben Java Basics - Anfänger-Themen 22
C Compiler-Fehler Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2 Java Basics - Anfänger-Themen 3
B Thread Problem Java Basics - Anfänger-Themen 7
N KeyListener in Thread Java Basics - Anfänger-Themen 0
M Thread.sleep() Funktion Java Basics - Anfänger-Themen 1
W JLabel in Main aus Thread verändern. Java Basics - Anfänger-Themen 4
D Ausgeben welcher Thread gerade Arbeitet Java Basics - Anfänger-Themen 8
N Threads Thread-Fehler Java Basics - Anfänger-Themen 2
F Thread um Uhrzeit ausführen Java Basics - Anfänger-Themen 5
F Get/Post als eigener Thread mit Rückgabe Java Basics - Anfänger-Themen 5
J Exception in thread "main" Java Basics - Anfänger-Themen 1
F Thread der auf eine Queue wartet, sicher beenden Java Basics - Anfänger-Themen 4
B Animation mit Thread(s) Java Basics - Anfänger-Themen 23
I Thread.sleep (1000); Java Basics - Anfänger-Themen 1
M Threads Jede Klasse einem Thread zuweisen Java Basics - Anfänger-Themen 7
J Java Thread cancel() und wiederbeleben Java Basics - Anfänger-Themen 4
J BouncingBalls 1 Thread Java Basics - Anfänger-Themen 3
L Fehler: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException Java Basics - Anfänger-Themen 4
J Timer oder Thread programmieren ? Java Basics - Anfänger-Themen 10
fLooojava Laufender Thread | Boolean ändern Java Basics - Anfänger-Themen 9
T Thread Pool mit Work Stealing Java Basics - Anfänger-Themen 1
R Java Thread Java Basics - Anfänger-Themen 10
J Welche Methoden laufen im neuen thread ?? Java Basics - Anfänger-Themen 9
S Java memory fehler: Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap spa Java Basics - Anfänger-Themen 5
K Thread - Methoden in die run Methode Schreiben Java Basics - Anfänger-Themen 5
N Threads Exception in thread "main"... Feher bei dem Versuch ein Radius zu berechnen Java Basics - Anfänger-Themen 4
A Code läuft nicht, Fehlermeldung Exception in thread "main" java.lang.Error: Unresolved compilation " Java Basics - Anfänger-Themen 11
V Threads Exception in Thread behandeln Java Basics - Anfänger-Themen 3
S Methoden Multi-Thread und Methoden Objects. Java Basics - Anfänger-Themen 1
J Thread erstellen (BlueJ Projekt) Java Basics - Anfänger-Themen 3
P Exception in thread "main" java.lang.NoClassDefFoundError: Java Basics - Anfänger-Themen 1
F Threads Variable aus einem Thread in main Methode? Java Basics - Anfänger-Themen 9
K Exception in thread "main" Java Basics - Anfänger-Themen 7
L Thread-Frage Java Basics - Anfänger-Themen 2
E Was ist ein idle-thread? Java Basics - Anfänger-Themen 1
D Exception in thread "AWT-EventQueue-0" Java Basics - Anfänger-Themen 8
J Threads Prozess in Thread auslagern Java Basics - Anfänger-Themen 2
G Thread mehrmals starten und schliessen Java Basics - Anfänger-Themen 6
F Thread Koordination (Vorteile/Nachteile) Java Basics - Anfänger-Themen 0
O Thread aus dem Thread stoppen Java Basics - Anfänger-Themen 6
O Swingworker/Thread Java Basics - Anfänger-Themen 3
R Focus auf JPanel im Thread Java Basics - Anfänger-Themen 9
S musik in eigenem thread Java Basics - Anfänger-Themen 2
A Klasse,Vererbung,Interface,Singleton,Thread Java Basics - Anfänger-Themen 5

Ähnliche Java Themen


Oben