Wybudzenie konkretnego wątku

0

Witam. Właśnie zaczynam pisać pewien program wykorzystujący wątki. Na planszy mam pudełko oraz latające kulki. Każde z nich to oddzielny wątek (pudełko oraz kulki mają własne klasy). Gdy kulka natknie się na ściankę pudełka, przykleja się do niej. Do wnętrza pudełka wpuszczana jest jedna kulka (pudełko jest wybudzane poprzez notify()). Wewnątrz pudełka może w danej chwili być tylko jedna kulka (pudełko w tym czasie ma wywołaną metodę wait()). Gdy kulka opuszcza pudełko, wpuszczona zostaje następna.
Niestety, nie wiem jak wysłać notify() do wątku obsługującego pudełko (na pewno realizowałaby to kulka wychodząca). Jeśli czeka jedna kulka to nie ma problemu, ale co jeśli jest ich kilka? Notify() działa losowo, więc najpewniej "trafi" inną kulkę. Prosiłbym o jakąś wskazówkę, jak rozwiązać ten problem.

0

Ja pamiętam 2 zasady:

  1. nie używaj wait i notify
  2. jeśli już używasz, to zapomnij o notify i używaj tylko notifyAll
0

Przyznam szczerze, że nie wiem skąd te zasady. Zgaduję, że chodzi o to, by wątek w międzyczasie mógł robić coś pożyteczniejszego niż bezczynne oczekiwanie.
Problem w tym, że zgodnie z treścią zadania, mam użyć właśnie wait() i notify(). Na liście metod, z którymi mam się zapoznać są natomiast: run(), start(), sleep(), interrupt(), suspend(), resume().

EDIT: Przeczytałem kilkukrotnie treść zadania. Nie wiem jakim cudem, ale pomieszały mi się warianty (jeden do wyboru). Przedstawiony przeze mnie wariant nie wymaga, by pudełko było wątkiem.
To moim zdaniem znacząco upraszcza sprawę. Natomiast wariant, który faktycznie wymaga tego dodatkowego wątku sprowadza się do rozwiązania problemu śpiącego golibrody.

0

Czy kulka agreguje (ma w sobie) wątek pudełka?
this(kulka).wątekPudelka.notify() ?

... w sumie nie wiem ;p

0

Nie. Zarówno kulka, jak i pudełko to oddzielne wątki. Oczywiście, jeśli rozpatrujemy wyżej wspomniany wariant z problemem śpiącego golibrody. W przeciwnym wypadku pudełko nie posiada swojego wątku, a jest tylko obiektem.

0

@Delor: Niezbyt dobrze rozumiem ideę kolejki blokującej. Czy chodzi o to, że wątek, który "wrzuci" kulkę do kolejki zostanie zablokowany do momentu wywołania metody ArrayBlockingQueue.take()?

0

Kolejkę tworzy się podaną wielkością.
Konsument pobiera z kolejki (take()). Jeżeli kolejka jest pusta to jest blokowany i czeka na element.
Producent wkłada do kolejki (put()) i jeżeli w kolejce skończy się miejsce to jest blokowany i czeka na zwolnienie miejsca.
Pary metod offer()/poll() i add()/remove() to dodawanie/wyjmowanie nieblokujące (zwracają bool lub rzucają wyjątek gdy nie mogą niezwłocznie wykonać operacji).
Metody offer()/poll() z timeoutami to wersje blokujące na pewien czas.

0

Czyli wątek, pomimo dodania czegoś do kolejki, wciąż się wykonuje.
Mam pewien pomysł. Pudełko co pewien czas mogłoby wydawać "bileciki", które byłyby odbierane przez kulki oczekujące na wejście.

EDIT: Wiem, że to dość głupie pytanie, ale czy możliwe jest, by w jednym "przejściu" kolejki ten sam wątek dwukrotnie dodał coś do niej?

0

Bilety to dobry pomysł.
Wątek może dodawać do kolejki ile zechce (do skończenia miejsca w kolejce).

0

Zastanawia mnie jedno: po co pudełko ma być wątkiem? Z treści zadania wynika, że wątkami mają być kulki, one się poruszają, przyklejają się do pudełka, wchodzą i wychodzą. Pudełko to zasób, który tylko ma synchronizować i koordynować kulki.
Pierwsze rozwiązanie to zrobić pudełko jako monitor, z dwoma metodami: enter() i exit(), obie synchronizowane. Obiekt pudełka ma licznik, ile kulek jest w środku. W enter(), najpierw testujesz, czy w pudełku jest dozwolona liczba kulek, zwiększasz licznik kulek i koniec, Jeśli brak miejsca na kulkę, to robisz wait() na obiekcie pudełka. W exit() wywołujesz notifyAll() jeśli liczba kulek w pudełku jest równa maksimum i zmniejszasz licznik kulek. W wątku kulek, przed wykonaniem ruchu, oceniasz gdzie znajdzie się kulka jeśli była na zewnątrz pudełka i ma wejść do pudełka to wywołuje enter(), jeśli była w środku i wychodzi to exit(), pozostałe warunki to sekcja lokalna.
Drugie rozwiązanie to wykorzystanie wspomnianej ArrayBlockingQueue, która będzie symulować swoim put() funkcję enter() a take() exit(), a długość kolejki liczbę dozwolonych kulek w pudełku.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0