Hallo an alle,
ich habe folgendes Problem:
ich habe ein Hauptthread (Th-1), der einen zweiten Thread (Th-2)
startet. (Th-2) soll dabei in einer while-Schleife laufen. Am Ende der
Schleife soll sich der Thread immer in den "wait()"-Modus versetzen,
also schlafen legen. (Th-2) soll solange schlafen bis (Th-1) notify()
aufruft. Dann beginnt bei Th-2 der nächste Schleifen durchlauf.
Zur Anmerkung: Beide Threads sind derzeit in einer Klasse.
Von der Theorie denke ich habe ich das Problem soweit gut verstanden,
nur habe ich Probleme bei der Umsetzung. Es gelingt mir zwar Th-2 mit
wait schlafen zu legen, jedoch nicht aufzuwecken.
Ich hoffe, dass mir jemand helfen kann.
Viele Grüße und vielen Dank im Voraus,
Fellowes
Der schlafende Thread sollte nicht einfach eine definierte Zeit warten,
sondern auf ein Synchronisationsobjekt warten.
Da Du praktischerweise nichts von Programmiersprache & Betriebssystem
verrätst, beschreibe ich mal einfach, wie man es mit der Win32-API
macht.
Ein geeignetes Synchronisationsobjekt ist hier das Event, das mit
CreateEvent erzeugt wird. Mit SetEvent kann es ausgelöst werden. Das
dürfte das Äquivalent Deines "notify" sein.
Darauf gewartet wird mit WaitForSingleObject, dabei kann die Zeit
angegeben werden, die maximal verstreichen darf -- der Rückgabewert von
WaitForSingleObject hilft, herauszufinden, ob das Event ausgelöst
wurde oder die Wartezeit verstrichen ist.
Alternativ gibt es auch WaitForMultipleObjects, damit kann auf mehrere
Events gleichzeitig gewartet werden.
Wie der Namensbestandteil ..Object(s) der Funktionen schon erahnen
lässt, kann mit ihnen auch auf andere Dinge als auf Events gewartet
werden, so z.B. direkt auf Threadhandles (die bei Beendigung des
zugehörigen Threads bedient werden).
Wait/Notify ist in 99% der Fälle der falsche Weg, es gibt sehr schöne
Highlevel Objekte in Java.
Ohne Code/Anwendungsfall kann man dazu Garnichts sagen außer, das wenn
man es richtig macht es auch funktioniert.
Es gibt prinzipiell kein Problem damit, beides in der gleichen Klasse zu
implementieren. Falls die Elternklasse ein Runnable-Klasse ist (so
klingen Deine Beiträge), kann damit aber nur ein Thread bedient werden
und für den zweiten Thread ist ein zweites Thread-Objekt nötig, das eine
andere Arbeitsmethode aufruft (falls nicht sowieso der Haupthread oder
ein anderer "externer" Thread der erste Thread ist).
Die Synchronisation kann man vielleicht auch mit wait() und notify()
machen, ich habe aber keine Erfahrung damit und würde es daher mit einer
Mutex-Semaphore machen. Der Ablauf ist folgender:
- Semaphore ist am Anfang freigegeben.
- T2 blockiert am Ende der While-Schleife die Semaphore
- T2 wartet auf die Semaphore
- T1 gibt sie frei
- T2 führt nächste Runde der While-Schleife aus usw.
Ich habe so was schon in C++ und in Java gemacht, habe aber leider
keinen Java-Beispielcode da. Es gibt eine Semaphoren-Klasse in
java.util.concurrent.Semaphore (muß mit Wert 1 initialisiert werden, um
fast das gleiche wie eine Mutex-Semaphore zu erhalten).
Was Dir noch weiterhelfen könnte, ist die Erklärung von
Thread-Programmierung aus dem Buch "Java ist auch eine Insel":
http://openbook.galileocomputing.de/javainsel9/javainsel_14_001.htm.
Siehe evtl. auch
http://www.oracle.com/technetwork/articles/javase/index-140767.html .
Matthias H. schrieb:> Synchronisation
Kann man nicht, Synchronisation muss vorher schon gesehen sonst hagelt
es Exceptions.
Matthias H. schrieb:> Thread-Objekt nötig, das eine andere Arbeitsmethode aufruft
Auch per se nicht korrekt... man könnte (und müßte) da die gleiche run()
Methode nehmen.
Läubi .. schrieb:> Matthias H. schrieb:>> Synchronisation>> Kann man nicht, Synchronisation muss vorher schon gesehen sonst hagelt> es Exceptions.
Ich wüßte nicht, wo diese herkommen sollten, außer man macht etwas
anderes falsch.
> Matthias H. schrieb:>> Thread-Objekt nötig, das eine andere Arbeitsmethode aufruft>> Auch per se nicht korrekt... man könnte (und müßte) da die gleiche run()> Methode nehmen.
Also, entweder habe ich nicht verstanden, was Du meinst oder Du möchtest
Du hier die Anfänger verwirren.
1. Es könnte technisch möglich sein, die gleiche run()-Methode zu
verwenden, wenn man aus dem 2. Thread die run()-Methode des 1. Threads
aufruft. Das ist aber ein schmutziger Hack, der noch eine externe
Fallunterscheidung erfordert (run() hat keine Parameter!), welche der
beiden Funktionalitäten nun ausgeführt werden soll. Es ist also
theoretisch möglich, aber nicht sinnvoll.
Steckst Du hier vielleicht gedanklich in der Semantik von UNIX-fork()
oder so, wo man das so ähnlich machen muß, was aber mit Java-Threads
nichts zu tun hat?
2. Wenn man beide Arbeitsmethoden in der gleichen Klasse haben möchte,
gibt es (unter anderem) folgende Möglichkeiten:
2a) Klasse implementiert Runnable für Thread 2, Thread 1 ist
"Hauptthread" oder "externer" Thread. Der Hauptthread ruft aber nicht
run() auf, sondern eine neue Methode.
2b) Klasse 1 implementiert Runnable für einen der beiden Threads und
enthält ein anderes von Runnable abgeleitetes Objekt der Klasse 2,
dessen run()-Methode z. B. eine neue Methode Klasse1.run2() in Klasse 1
aufruft. Dazu muß Klasse 2 eine Referenz auf das Objekt von Klasse 1
halten.
2c) Aggregation, neue Klasse 3 enthält zwei von Runnable abgeleitete
Objekte von Klasse 1 und Klasse 2. Deren run()-Methoden könnten dann
neue Methoden Klasse3.run1() und Klasse3.run2() aufrufen.
Matthias H. schrieb:> Ich wüßte nicht, wo diese herkommen solltenhttp://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait%28%29>> Throws:>> IllegalMonitorStateException - if the current thread is not>> the owner of the object's monitor.
Heißt: du darfst dies nur innerhalb eine syncronized Blocks aufrufen,
ergo ist die Synchronisation dann schon geschehen.
Matthias H. schrieb:> Es könnte technisch möglich sein, die gleiche run()-Methode zu> verwenden, wenn man aus dem 2. Thread die run()-Methode des 1. Threads> aufruft
Es reicht schon beides mal das gleiche Runnable Objekt zu übergeben, das
ist nicht verboten.
> der noch eine externe Fallunterscheidung erfordert
Nö, es kann genauso gut sein, das ich innerhalb der Run Methode von
außerhalb Parameter einlese, mir errechne, ...
Matthias H. schrieb:> Steckst Du hier vielleicht gedanklich in der Semantik von UNIX-fork()
Nö, aber der TE kommt ja nicht aus dem Quark, hier irgendwas zu mutmaßen
aufgrund von
Fellowes schrieb:> Beide Threads sind derzeit in einer Klasse
ist doch sehr gewagt...
Matthias H. schrieb:> Das ist aber ein schmutziger Hack
Ach und eine run1(), run2() und run3() trägt nun zur allgemeine
Erleuchtung bei ;-P
Das ist doch erst recht Käse...
Ohne konkretes Problem/Code kann man hier doch eh nix vernünftiges Raten
und aufgrund der spärlichen Informationen noch nicht mal richtig
mutmaßen....
Läubi .. schrieb:>> Ich wüßte nicht, wo diese herkommen sollten>> http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait%28%29>>>> Throws:>>> IllegalMonitorStateException - if the current thread is not>>> the owner of the object's monitor.>> Heißt: du darfst dies nur innerhalb eine syncronized Blocks aufrufen,> ergo ist die Synchronisation dann schon geschehen.
Das ist genau der Grund, warum ich eine Lösung mit Semaphore anstelle
von wait()/notify() vorgeschlagen hatte.
Matthias H. schrieb:> anstelle von wait()/notify() vorgeschlagen hatte
Ja und ich hab schon ganz am Anfang gesagt das es fast immer bessere
Lösungen gibt. Aber da der TE ja nicht mit Details rausrückt...