Forum: PC-Programmierung wait(), notify()


von Fellowes (Gast)


Lesenswert?

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

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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

von Fellowes (Gast)


Lesenswert?

Ohh hatte ganz vergessen zu erwähnen, dass es in Java implementiert wird 
und auf einem Android Tablet laufen soll

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Tja, dann wirst Du Dir die Java-Dokumentation zu Gemüte führen müssen 
und Dir dort Synchronisationsobjekte ansehen.

Ich kenne Java nicht weiter, aber vielleicht hilft Dir ja das hier:
http://www.fh-wedel.de/~si/vorlesungen/java/OOPMitJava/Multithreading/Synchronisation.html

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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.

von Matthias H. (experimentator)


Lesenswert?

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 .

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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.

von Matthias H. (experimentator)


Lesenswert?

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.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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

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

von Matthias H. (experimentator)


Lesenswert?

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.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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

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.