Bevásárlás a Fokeában járvány idején
A Fokea Lakberendezési Áruház a világjárvány idején is szeretné kiszolgálni vásárlóit. Azonban a járványügyi korlátozások miatt speciális intézkedéseket kellett bevezetnie: egyszerre csak n ember tartózkodhat az áruházban, továbbá az áruház teljes területén kötelező megtartani a másfél méter távolságot.
Készítsünk szimulátort, amely a tipikus Fokea vásárlók szokásait és a járványügyi szabályozások betartását is figyelembe veszi! A megoldás során fektess hangsúlyt a szálbiztos megoldásra (hiszen ezt fogjuk nézni elsősorban :))!
[+1 tipp: próbálj olvasható / Java-s konvenciókat betartó kódot készíteni, hiszen ez is része a ZH-jegynek!]
#
Feladatok#
Alapfeladat (4 pont)- Biztonsági őr (
SecuMan
osztály):- egy szemaforral tartja számon, illetve szabályozza, hogy éppen hányan vannak benn
- ezt megosztja a többi biztonsági őrrel (ezért konstruktorának paramétereként kapja)
- a Fokea több bejárattal rendelkezik, ezért fontos, hogy mindegyik őr lássa, hogy épp hányan vannak benn
- az
enter
ésexit
metódusokkal lehet megpróbálni átjutni egy biztonsági őrön, ami csak akkor sikerül, ha van még szabad kapacitás
Fokea
osztály:- 2 biztonsági őrt hoz létre a jobb, illetve a bal kapuhoz
- az aktuális szabályozások alapján beengedhető emberek maximális számát a konstruktorban kapja meg
- az
enter
ésexit
metódusai a megfelelő kapunál álló őr azonos nevű metódusait hívják - a kapuk (jobb és bal) legyen egy enum típusba tartozók, melyet az
enter
/exit
paraméterül kap Person
osztály:- egy szálat valósít meg
- konstruáláskor megkapja a Fokea referenciáját
- tevékenysége:
- kezdetben véletlen ideig sétafikál (várakozik) (1-15 mp)
- belép a Fokeába (választ egy kaput véletlenszerűen)
- véletlen ideig nézelődik, vásárolgat (várakozik) (1-20 mp)
- elhagyja a Fokeát
- a main metódusban hozz létre egy
Fokea
objektumot, valamint embereket (lista), és indítsd is el a hozzájuk tartozó szálat - a maximálisan beengedhető létszámot állítsd kevesebbre, mint ahány vásárló (lézengő) lesz
#
Plüssnyúl (4 pont)a
Person
osztály ne legyen a szál leszármazottja, másképp oldd meg, hogy futtatható legyen egy szálongondoskodj róla, hogy a randomszám generálás szálbiztos legyen, úgy, hogy minden szál ugyanazt a randomszám generátort használja
a
Fokea
osztály rendelkezzen egybuyBunny
művelettel, mely a következőképp működik:- egy
Person
objektumot kap paraméterül, aki megpróbál plüssnyulat venni - azonban a másfél méter betartása végett egyszerre csak 1 ember mehet a plüssnyúl tároló közelébe
- gondoskodj róla, hogy egyszerre csak 1 szál hívhassa meg a metódust, de ügyelj rá, hogy ez ne tartsa fel a beléptetést/kilépést (azok a szálak ne blokkolódjanak azért, mert valaki plüssnyulat vesz) (Tipp: ne a Fokea-hoz tartozó mutex-et használd!)
- fix darabszámú plüssnyúl áll rendelkezésre (50), ezt számon kell tartani a
Fokea
objektumban - egészítsd ki a
Person
tevékenységét egy plüssnyúl vásárlással + további nézelődéssel (a kezdeti nézelődés után, az áruház elhagyása előtt) - a
Person
objektum mielőtt elveszi plüssnyulat, véletlen ideig filóz, hogy melyik is legyen… (1-5mp), mindezt természetesen akkor teszi, amikor már bejutott abuyBunny
metódusba (hogy a többiek még véletlenül se végezzenek időben…) - az elvétel után csökken a plüssnyulak darabszáma 1-el
- ha valakinek már nem jutott plüssnyúl, sír és hazamegy:
cryAndGoHome
metódus, mely véletlen ideig vár (pár msp), majd kimegy a Fokeából
- egy
#
Családok (4 pont)- mivel mindenki szeret családostul menni a Fokeába, legyen egy
Family
osztály - a
Family
osztály egy listában tartja számon a családtagokat, valamint a Fokea-ra is van referenciája - mivel a család tagjai nem képesek önálló létezésre, ezért egyszerre kell be-, illetve kilépniük
- ehhez legyen
enterFokea
ésexitFokea
művelet - a
Fokea
/SecuMan
osztályok nyújtsanak lehetőséget arra, hogy a családosok egyszerre tudjanak belépni/kilépni (mindent vagy semmit) (Tipp: kelleni fog egy-egy extra paraméter a műveleteknek) - a
Person
osztály kapja meg a családját referenciaként (ha van) - a családos ember nem megy be/ki egyedül, helyette a
Family
megfelelő műveletét használja, módosítsd aPerson
osztályt a megfelelő módon - FONTOS: ügyeljünk rá, hogy ha az egyik családtag már kezdeményezte a belépést/kilépést, a többiek már ne tudják a Fokea
enter
/exit
műveleteit meghívni (ez elrontaná a számítást) [Tipp: boolean flag + mutex] - a
main
-ben hozz létre pár családot is; érdemes lehet egystart
metódust írni aFamily
-be, ami elindítja a családtagok szálait
#
Raktáros (4 pont)- mivel az egyes családtagok nem egyszerre végeznek, érd el, hogy a kilépés előtt várják be a többieket
- ehhez érdemes lehet a
java.util.concurrent.CountDownLatch
osztályt használni - legyen szálat megvalósító raktáros (
Storekeeper
), aki a plüssnyulak feltöltéséért felel- működése nagyon egyszerű: ha elfogynak a plüssnyulak, visszatölti az eredeti darabszámot
- ehhez persze figyelnie kell, mikor fogynak ki és lehetőleg addig a pontig várakoznia (blokkolni)
- valamint tudnia kell épp hány darab plüssnyúl van a Fokeában (lehet pl belső osztály az egyszerűség végett)
- mindehhez érdemes lehet vagy a
java.util.concurrent.LinkedBlockingQueue
, vagyLock
+Condition
osztályok használata - ügyelj rá, hogy a fentieket szálbiztos módon valósítsd meg!
- a
Storekeeper
álljon le, ha legalább 1 percig nem kap kérést feltöltésre