Gyakran észrevesszük, hogy a programok futtatásakor vannak bizonyos korlátok. Például egyszerre általában csak egyetlen telepítőprogram futhat egy operációs rendszeren. Vagy amíg fut egy program korábbi verziójának eltávolítása, addig nem futhat a program új verziójának telepítője. Vagy egy nagyobb erőforrás igényű program (periféria meghajtó program, képernyő videó+hang rögzítő, hardveres gyorsítást használó játékprogram) egyszerre csak egy példányban indítható el. Előfordulhat kategóriánkénti korlát is, például a különböző víruskereső programok általában „nem tűrik meg” egymást, kizárólagosságot „követelnek”.
Lássunk példát arra, hogyan kell készíteni egy példányban futó Java programot!
Néhány dolgot át kell gondolni:
- Amikor először indítjuk el a programot, akkor olyan egyedi dolgot kell beállítani, ami mindvégig úgy marad, amíg a program fut. Ezt megtehetjük a memóriában, de megfelelő jogosultsággal futtatva a programot akár beleírhatunk a Windows rendszerleíró adatbázisába (Registry) is. Előbbi módszer platformfüggetlen lenne – ahogyan egy Java programhoz illik –, és az utóbbi megoldás pedig operációs rendszertől függne.
- Amikor többedszer (második, harmadik… példányban) indítjuk el a programot, akkor ezt az egyedi dolgot észlelni kell és meg kell akadályozni a program másodszori, harmadszori elindítását. Hasznos, ha ezekben az esetekben kapunk hibaüzenetet, például: „This application is already running”.
- Amikor a programot szabályosan állítjuk le, akkor a korábban beállított egyedi dolgot semmissé kell tenni. Ez biztosítja, hogy a program egymás után – egymással nem párhuzamosan, egymástól függetlenül – elindítható lesz.
A megoldás két részből áll. Ez a Java forráskód első része:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
private static ServerSocket ss=null; static { try { ss=new ServerSocket(65001, 10, InetAddress.getLocalHost()); } catch(UnknownHostException e) { ; } catch(IOException e) { JOptionPane.showMessageDialog(null, "This application is already running.", PROGRAM_STUDENT_TITLE, JOptionPane.ERROR_MESSAGE); System.exit(0); } } |
A program indulásakor le kell futni a fenti forráskódnak. A static blokk a konstruktor előtt hajtódik végre (például a modell vagy a nézet rétegben). A java.net csomag kötetlen ServerSocket osztályú ss nevű objektumát kell inicializálni helyben ( InetAddress.getLocalHost()) egy nem dedikált porttal ( 65001). Ez elsőre mindig sikerült és az objektum „beül a memóriába” egy nem blokkoló elven működő háttérszálon. Ha (többedszerre) nem sikerül létrehozni az objektumot, akkor – kezelve a kötelezően kezelendő kivételeket – hasznos jelezni ezt logban, konzolon vagy felbukkanó párbeszédablakban és a programból ki kell lépni (másképpen: a duplikált futtatását meg kell akadályozni).
Ez a Java forráskód második része:
1 2 3 4 5 6 7 8 |
try { //a program csak 1 példányban futhat if(ss!=null && !ss.isClosed()) ss.close(); System.exit(0); } catch(IOException e) { ; } |
A programból való szabályos kilépéskor le kell futni a fenti forráskódnak. Ez ellenőrzést követően lezárja az ss objektumot és kilép a programból. Például a main() metódusban, ha elfogynak az utasítások egy konzolos alkalmazásban, vagy GUI-s programban nyomógombra kattintás actionPerformed() esemény, vagy (fő)ablak bezárásának kísérlete WindowClosing() esemény.
A programot érdemes körültekintően tesztelni. Ha elrontjuk a fenti felsorolásban vázolt logikai működés végrehajtásának sorrendjét, akkor fejlesztés vagy tesztelés közben akár a számítógépet is újra kell indítanunk.
A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.
A Java EE szoftverfejlesztő tanfolyamunkon, a szakmai modul 5-8. óra Szálkezelés, párhuzamosság alkalommal megismerjük a megoldás elméleti hátterét és a 17-24. óra Socket és RMI alapú kommunikáció alkalommal többféle megvalósítást is kódolunk, tesztelünk.
Balázs: az egyik korábbi Java EE órán beszéltünk arról, hogy a chatprogramba beépíthető olyan korlát, hogy a szobákban hányan tudjanak belépni. Megpróbálnám megoldani ezt. Továbbgondolva Sándor fix korlát=1 megoldását módosítható korlát=n-re. Jó ötlet hozzá a
ServerSocket
használata?András: ha a programodban minden szobában ugyanaz (statikus) a korlát, akkor a
ServerSocket
jó megoldás. Ha szobánként különböző korlátokat szeretnél, vagy esetleg a futás közben szeretnéd beállíthatóvá tenni a korlátot, akkor arra a jövő heti órán nézünk egy praktikusabb (dinamikus) megoldást.Addig is gondold át szálkezeléshez kötődő projektjeinket (a teljes Java forráskódokat az ILIAS-on találod).