[ me-tuzalem @ 15.11.2004. 10:07 ] @
Naslov teme nije baš najprecizniji, ali evo o čemu se radi.
Imam jednu klasu koja je singleton(pattern).
U njoj su dve metode npr.

posaljiZahtev()...

primiOdgovor()...

U aplikaciji kreiram odvojene Threadove koji koriste ovu singleton klasu, tj. njenu jedinu instancu.
Zahtevi se generisu u okviru jednog threada, a odgovor u okviru drugog i to asinhrono. Problem mi je sa sinhronizacijom hvatanja odgovora. Kada odgovor stigne bez zahteva jednostavno ga odbacim. Ali kada je zahtev poslat, hoću da sačekam odgovor pre nego što prihvatim sledeći zahtev.
Želim da u posaljiZahtev() ubacim čekanje na odgovor.
Probao sam sa
wait()

a u primiOdgovor() sa:
notifyAll()

ali mi javlja:IllegalMonitorStateException - the current thread is not the owner ...
i to u svim slučajevima, bez obzira u kom Threadu sam inicijalno instancirao singleton.
Nisam želeo da koristim suspend() i resume() iako bih verovatno izbegao deadlock, ali ne volim depreciated metode.
Ima li neko ideju kako da ovo prevaziđem ?

[ me-tuzalem @ 15.11.2004. 10:53 ] @
Zaboravio sam da napomenem da sam pokušavao da obe pomenute metode budu syncronized ili da celo telo tih metoda bude u okviru
synchronized(this){...}
Prema Java dokumentaciji time bi trebalo da izbegnem pomenut Exception, ali nije tako.
[ hyle @ 15.11.2004. 11:35 ] @
Nije mi jasno zbog čega implementiraš asinhronu komunikaciju ukoliko Thread koji šalje zahtev čeka sve dok ne dobije odgovor? Zar to nije obična sinhrona komunikacija ili te ja nisam nešto razumeo?
Programiranje sa više Thread-ova treba izbegavati i koristiti ga jedino ukoliko problem ne može da se reši klasičnim pristupom ili ukoliko si apsolutno siguran da znaš šta radiš. Komplikuje se debug, moguće je javljanje deadlock-ova, moraš da vodiš računa o stanju Thread-ova...

Što se tiče synchronized metoda...
Pretpostavimo da klasa C ima metode a() i b() i da imamo instancu klase C pod nazivom c.
Ukoliko iz jednog Thread-a pozovemo c.a() pozivi metoda a() ili b() iz drugih Thread-ova biće blokirani sve dok se ne završi poziv metode iz prvog Thread-a. U trenutku dok se izvršava synchronized metoda, za Thread koji ju je pozvao kaže se
Citat:
thread is the owner of this object's monitor
i sve dok on ne oslobodi monitor ostali thread-ovi neće moći da pristupe tom synchronized resursu.

Što se tiče IllegalMonitorStateException-a koji ti se javlja, u help-u za metode wait() i notify() piše:
Citat:
This method should only be called by a thread that is the owner of this object's monitor.
...
Throws: IllegalMonitorStateException - if the current thread is not the owner of this object's monitor.


Najbolje bi ti bilo da potražiš na netu neki tutorial za rad sa Thread-ovima u Javi pošto nije u pitanju mala oblast i teško ti neko može objasniti sve što ti treba na forumu. Evo pogledaj Using the notifyAll and wait Methods na Sun-ovom sajtu, to može da ti bude početak.

Pozdrav
[ me-tuzalem @ 15.11.2004. 12:09 ] @
Kao prvo, imam dva izvora asinhronih događaja.
Jedan je iniciran od nekog klijenta, a drugi je uređaj koji je na serijskom portu.
Na COM portu se generišu događaji, i kada im nije prethodila akicija operatera, obrađuju se na jedan način. A kada im je pak prethodila akcija klijenta, obrađuju se na drugi način.
Nakon akcije klijenta, niz bajtova sa uređaja se tretira kao odgovor.
Nakon tog niza, preostali bajtovi se tretiraju drugačije.
Pretpostavljam da je iz ovoga jasno zašto Threadovi.
Ja sam i u prvom postu napisao:
Citat:
Kada odgovor stigne bez zahteva jednostavno ga odbacim.

Moguće da ti je promaklo ono bez zahteva. A nažalost, ne odbacujem ga bukvalno, već sam tako napisao da nih komplikovao priču.

A što se tiče tvoje napomene o synchronized , ja sam upravo da bi Thread koji se izvršava postao vlasnik object's monitora i koristio synchroized, inače ne bih, jer mi nije potrebno iz drugih razloga. Međutim, izgleda da na taj način ne postaje monitor objekta i na znam kako da prevaziđem problem.
[ filmil @ 15.11.2004. 12:30 ] @
Citat:
ali mi javlja:IllegalMonitorStateException - the current thread is not the owner ...
i to u svim slučajevima, bez obzira u kom Threadu sam inicijalno instancirao singleton.
Za razliku od nekih drugih programskih jezika, Java daje poruke koje pomažu nalaženje greške.

Dakle, da bi ijedna nit mogla da čeka unutar nekog objekta (wait()), mora da postane vlasnik semafora za taj objekat. Pogledaj dokumentaciju za notify(). Tamo piše na koji način to može da se uradi. Video sam i drugu tvoju poruku u kojoj kažeš da si dodao synchronized; meni deluje ipak da si negde propustio da to uradiš, ili da si zaboravio da kompajliraš posle izmene; ili tako nešto.

Deluje i da nema mnogo smisla praviti dve niti ukoliko jedna uvek i svuda čeka da druga završi. Ako se uvek i bezuslovno čeka, onda sve može da se odradi i u okviru samo jedne niti.

Takođe mi se čini da možeš da imaš na problem sa sinhronizacijom jer ne može da se garantuje da će notifyAll() da pokrene drugu nit baš u onom stanju koje ti misliš da će biti. Na primer, kada stigne taj out of sequence odgovor, a ti čekaš na neki drugi odgovor, notifyAll() će pokrenuti thread iako odgovor nije pravi. Pomoglo bi da opišeš detaljnije šta pokušavaš da napraviš.

f
[ filmil @ 15.11.2004. 12:43 ] @
Citat:
Jedan je iniciran od nekog klijenta, a drugi je uređaj koji je na serijskom portu.
Aha, sad je malo jasnije.

Citat:
Moguće da ti je promaklo ono bez zahteva.
Ne verujem da je promaklo. Možda ne primećuješ pošto si „unutar“ problema, ali od spolja gledano, uopšte nije jasno definisano šta to znači da se nešto desilo bez zahteva. Otud i dobijaš odgovore koji su čudni (tj. izgledaju neprimenljivi u tvom slučaju).
Citat:
A nažalost, ne odbacujem ga bukvalno, već sam tako napisao da nih komplikovao priču.
Sa ovakvom postavkom imaš:

- jednu nit koja obrađuje serijski port. Za hvatanje znakova ne može da se izbegne jedna nit. Odnosno mogla bi kada bi mogao da garantuješ da ćeš pokupiti znake pre nego što se bafer prepuni.
- Ova nit bezuslovno znake stavlja u red (Queue).
- Znake iz reda kupi druga nit koja je interno FSM patern (finite state machine). Ona se izvršava u posebnoj niti, takođe, i ima javne metode kojima korisnik može da menja stanje. Tako bi recimo mogao da napraviš dva stanja: jedno (s1) u kome bi se znaci samo skidali iz reda i ignorisali; i drugo (s2) u kome bi se skidali iz reda i ispisivali (ili bi se radila bilo koja druga obrada, po želji).

Podrazumevano stanje bi bilo (s1);

Na poruku setStateS2() u stanju s1 bi mašina prešla u s2; na poruku setStateS1() u stanju s2 bi mašina prešla u s1. Ostale metode su prazne (tj. u stanju s2 setStateS2() ne radi ništa. Slično za s1 i odg. metodu).

Pravljenje ovakve klase bi, osim što je pregledno, moglo da se upotrebi i da se dokaže da tvoj program ispravno radi.

f
[ hyle @ 15.11.2004. 13:25 ] @
Rešenje koje ti je predložio filmil i meni deluje OK ali imaćeš ti tu još problema.
Npr. šta ćeš raditi ukoliko ti neposredno nakon akcije operatera stigne nešto sa COM porta što ne predstavlja odgovor, a odgovor stigne tek nakon toga...

Mislim da bi ti po pitanju konačnog automata (finite state machine) bilo korisno da pogledaš nešto i o State Pattern-u iz knjige Design Patterns koju je napisao čuveni "Gang of Four".
[ filmil @ 15.11.2004. 13:27 ] @
Citat:
Npr. šta ćeš raditi ukoliko ti neposredno nakon akcije operatera stigne nešto sa COM porta što ne predstavlja odgovor, a odgovor stigne tek nakon toga...
Zato sam i predložio FSM; tako može da napravi dijagram (na hartiji, ili na računaru) i da istrese sve moguće patološke slučajeve koje nije obradio.

f
[ me-tuzalem @ 15.11.2004. 13:49 ] @
Filmil je razumeo priču. Prihvatam kritiku da je moje prvo pitanje nedovoljno precizno, ali ne volim dugačke postove, pa sam pokušao sa minimalnim brojem reči da opišem problem, da ne bih opterećivao nepotrebnim detaljima. Upravo su nekome ti detalji neophodni da razume priču.
Finite state pattern je prvo što sam primenio, pa mi nešto nije išlo. Možda nisam bio dovoljno uporan, pa sam pokušao nešto drugo, što mi je delovalo jednostavnije, ali ispalo je naopako. Vratiću se prvobitnoj ideji, ali ću biti malo uporniji.
Hvala na savetima.
[ hyle @ 15.11.2004. 14:10 ] @
Citat:
me-tuzalem: ...pa sam pokušao sa minimalnim brojem reči da opišem problem, da ne bih opterećivao nepotrebnim detaljima. Upravo su nekome ti detalji neophodni da razume priču.


Forumi su super stvar, brzo se dolazi do informacija ali imaju i svoje nedostatke.
Učesnici zasnivaju pretpostavke o čoveku koji piše samo na osnovu poruke koju je napisao i vrlo lako može doći do zabune i skretanje sa teme, zbog toga moraju pažljivo da se biraju reči.