Wybudzenie konkretnego wątku

Odpowiedz Nowy wątek
2018-12-27 21:01
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.

edytowany 1x, ostatnio: kst142, 2018-12-27 21:02

Pozostało 580 znaków

2018-12-27 21:35
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

Pozostało 580 znaków

2018-12-27 21:47
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.

edytowany 1x, ostatnio: kst142, 2018-12-27 23:02
Używanie wait i notify to proszenie się o kłopoty (chyba że naprawdę umiesz i rozumiesz programowanie współbieżne). Powinno się używać czegoś działającego i sprawdzonego, np: java.util.concurrent.ArrayBlockingQueue. Tylko tak, dla informacji (bo prowadzący raczej nie uzna takiego rozwiązania). - Delor 2018-12-28 00:30
W wariancie z wątkiem boxa nie zostało określone, czego mam użyć, więc tam to rozwiązanie mogłoby przejść :) - kst142 2018-12-28 00:35

Pozostało 580 znaków

2018-12-28 16:03
0

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

... w sumie nie wiem ;p

edytowany 1x, ostatnio: krsp, 2018-12-28 16:04

Pozostało 580 znaków

2018-12-29 02:27
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.

Pozostało 580 znaków

2018-12-30 00:38
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()?

Pozostało 580 znaków

2018-12-30 01:00
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.

Pozostało 580 znaków

2018-12-30 19:50
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?

edytowany 1x, ostatnio: kst142, 2018-12-30 22:18

Pozostało 580 znaków

2018-12-31 18:50
0

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

Pozostało 580 znaków

2018-12-31 20:55
cs
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.

Pozostało 580 znaków

2019-01-03 01:11
0

Dzięki za podpowiedź. Pudełko ma być wątkiem, ponieważ tak to zostało przedstawione w treści zadania.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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