konkurentn é programovanie v jave
DESCRIPTION
Franti šek Galčík. Konkurentn é programovanie v JAVE. Príklad na úvod. Jednoduchá GUI aplikácia Dlho trvajúca akcia blokuje hlavný „tok vykonávania príkazov“ v programe: pomalé I /O, sie ťová komunikácia (download z Internetu) d lho trvajúci výpočet - PowerPoint PPT PresentationTRANSCRIPT
KonkurentnKonkurentnééprogramovanieprogramovaniev JAVEv JAVE
František Galčík
22
Príklad na úvodPríklad na úvod
Jednoduchá GUI aplikáciaJednoduchá GUI aplikácia
Dlho trvajúca akcia Dlho trvajúca akcia blokujeblokuje hlavný „tok hlavný „tok vykonávania príkazov“ v programe:vykonávania príkazov“ v programe:
pomalé Ipomalé I/O, sie/O, sieťová komunikácia ťová komunikácia (download z (download z Internetu)Internetu)
ddlho trvajúci výpočetlho trvajúci výpočet
Jednoduché riešenie: Vytvoriť Jednoduché riešenie: Vytvoriť ““podprocespodproces” ” ssúbežne bežiaciúbežne bežiaci s hlavným programom, ktorý s hlavným programom, ktorý bude bude zdieľaťzdieľať s hlavným programom s hlavným programom haldu haldu (“svet, (“svet, v ktorom v ktorom žijú objektyžijú objekty”)”)
33
VlVlákno - Threadákno - Thread
Simultálne bežiaca podúlohaSimultálne bežiaca podúloha
Každá aplikácia má Každá aplikácia má aspoň jedno vláknoaspoň jedno vlákno, ktoré , ktoré sa vytvorí pri štarte aplikácie a v ktorom sa sa vytvorí pri štarte aplikácie a v ktorom sa začne vykonávať „main“začne vykonávať „main“
44
Vytvorenie vláknaVytvorenie vláknaVlákna môžu vytvárať nové vláknaVlákna môžu vytvárať nové vlákna
Kľúčová trieda:Kľúčová trieda: java.lang.Threadjava.lang.Thread
2 základné spôsoby vytvorenia vlákna:2 základné spôsoby vytvorenia vlákna:
RozšírenímRozšírením triedy triedy ThreadThread a prekrytím metódy a prekrytím metódy runrun
Implementovaním Implementovaním rozhrania rozhrania RunnableRunnable
Akcie, ktoré má Akcie, ktoré má (s(súbežneúbežne) ) vykonať vlákno vykonať vlákno ssú ú definované v metóde definované v metóde runrun()()
Po vykonaní metódy Po vykonaní metódy runrun()() vlákno vlákno prestprestáva áva existovaťexistovať (objekt triedy (objekt triedy Thread Thread reprezentujúci reprezentujúci vlákno vlákno vvšak môže existovať ďalejšak môže existovať ďalej))
Vykonávanie vlákna sa štartuje metódou Vykonávanie vlákna sa štartuje metódou startstart()()
55
PrPríklad vytvorenia vláknaíklad vytvorenia vlákna
Vytvorenie vlákna rozšírením triedy Vytvorenie vlákna rozšírením triedy ThreadThread: :
Vytvoríme vlákno, ktoré bude zadaný čas vypisovať Vytvoríme vlákno, ktoré bude zadaný čas vypisovať určený text pomocou objektu „vypisovača“určený text pomocou objektu „vypisovača“
Vytvorenie vlákna implementovaním rozhrania Vytvorenie vlákna implementovaním rozhrania RunnableRunnable
PozastaveniePozastavenie vykonvykonávania vlákna na stavovený ávania vlákna na stavovený čas:čas:
Thread.sleepThread.sleep(…);(…);
66
Čo nám ponúka trieda ThreadČo nám ponúka trieda Thread
VlVlákno patrí do nejakej ákno patrí do nejakej ThreadGroupThreadGroup
Skupinové riadenie vlákienSkupinové riadenie vlákien
Vlákno môže pristupovať len k vláknam zo svojej Vlákno môže pristupovať len k vláknam zo svojej ThreadGroupThreadGroup a jeho podskupín a jeho podskupín
Stromová Stromová hierarchiahierarchia skupín skupín
2 druhy vlákien:2 druhy vlákien:
Používateľské Používateľské (User)(User)
DaemonDaemon ((setDaemonsetDaemon, , isDaemonisDaemon))
Aplikácia končíAplikácia končí, ke, keď ď skončiaskončia všetky všetky užívateľskéužívateľské vlákna vlákna (za daemonmi sa ne(za daemonmi sa nečakáčaká))
77
Čo nám ponúka trieda ThreadČo nám ponúka trieda Thread
Riadenie Riadenie prioritypriority vl vlákna ákna ((setPriority/getPrioritysetPriority/getPriority):):
1 najni1 najnižšia, 5 default, 10 najvyššiažšia, 5 default, 10 najvyššia
Nastavenie Nastavenie ClassLoaderaClassLoadera pre dan pre dané vláknoé vlákno
Statická metóda Statická metóda Thread.currentThreadThread.currentThread()()
Vráti referenciu na objekty triedy Vráti referenciu na objekty triedy ThreadThread, , reprezentujúci bežiace vláknoreprezentujúci bežiace vlákno
Užitočné pre vlákna vzniknuté implementovaním Užitočné pre vlákna vzniknuté implementovaním RunnableRunnable
88
Ako predčasne ukončiť vlákno Ako predčasne ukončiť vlákno ??
Java Java neponúkaneponúka možnosť možnosť predčasnéhopredčasného ukončenia vláknaukončenia vlákna
Je možné poslať vláknu požiadavku na Je možné poslať vláknu požiadavku na ukončenie: metóda ukončenie: metóda interruptinterrupt()()
VlVlákno informáciu o požiadavke ákno informáciu o požiadavke zistízistí::
Získaním informácie metódou Získaním informácie metódou isInterruptedisInterrupted()() alebo alebo interrupted()interrupted()
Vznikom výnimky Vznikom výnimky InterruptedExceptionInterruptedException počas počas operácií, kedy je vlákno „uspaoperácií, kedy je vlákno „uspanné“é“
99
KooperKooperácia medzi vláknamiácia medzi vláknami
Zasielanie požiadaviek Zasielanie požiadaviek (nastavenie pr(nastavenie príznakuíznaku) ) na na ukončeniaukončenia
MetMetóda óda t.t.joinjoin()():: pozastav pozastaví vykonávanie vlákna, í vykonávanie vlákna, až kým vlákno t neskončíaž kým vlákno t neskončí
Príklad:Príklad: Ako to vyzerá, keď vlákna nefungujú Ako to vyzerá, keď vlákna nefungujú tak, ako majú....tak, ako majú....
1010
Vlákien je veľa a procesorov máloVlákien je veľa a procesorov málo
V určitom okamihu V určitom okamihu môže bežať najviac môže bežať najviac toľko vlákien, koľko toľko vlákien, koľko máme k dispozícii máme k dispozícii procesorovprocesorov
Ilúzia súbežného Ilúzia súbežného behu: behu: time-slicingtime-slicing
1111
Vlákna a Vlákna a pamäťpamäť
Každé vláknoKaždé vlákno::
má svoj má svoj vlastný stackvlastný stack, kde , kde sú uložené lokálne sú uložené lokálne premennépremenné
zzdiedieľa heapľa heap, kde sú vytvárané objekty, kde sú vytvárané objekty
1212
Problémy synchronizácieProblémy synchronizácieAA = 0;= 0;
A++;A++;
if (A > 0) if (A > 0)
System.out.print(A);System.out.print(A);
AA = 0;= 0;
A++;A++;
if (A > 0) if (A > 0)
System.out.print(A);System.out.print(A);
AA = 0;= 0;
A++;A++;
if (A > 0) print(A);if (A > 0) print(A);
AA = 0;= 0;
A++;A++;
if (A > 0) print(A);if (A > 0) print(A);
1313
MonitoryMonitory
Monitory zabezpeMonitory zabezpečujú pre vlákna:čujú pre vlákna:
vzájomné vylúčenievzájomné vylúčenie (mutual exclusion)(mutual exclusion)
kooperkooperáciuáciu
S kaS každým objektom je ždým objektom je asociovanýasociovaný monitor monitor
Monitor Monitor kontrolujekontroluje vykonávanie istých častí vykonávanie istých častí kódu: kódu: kritickkritických sekciíých sekcií asociovaných s asociovaných s monitorommonitorom
V každom okamihu V každom okamihu môže vlastniťmôže vlastniť monitor monitor (vykon(vykonávať kód kritickej sekcie monitoraávať kód kritickej sekcie monitora)) nanajvýš jedno vláknonanajvýš jedno vlákno
1414
Monitory v kódeMonitory v kóde
synchronized (objekt) {
.... kód kritickej sekcie monitora asociovaného s objektom objekt ...
}
Ak chceme synchronizovať celý kód metódy voči Ak chceme synchronizovať celý kód metódy voči monitoru asociovanému objektu monitoru asociovanému objektu thisthis, stačí pridať , stačí pridať „„synchronizedsynchronized“ ku hlavičke inštančnej metódy“ ku hlavičke inštančnej metódy
1515
Problém producenta a konzumentaProblém producenta a konzumentaSklad s Sklad s obmedzenouobmedzenou kapacitou kapacitou
Producent Producent produkujeprodukuje položky položky a vklad a vkladá ich do skladu, ak á ich do skladu, ak je v sklade voľné miestoje v sklade voľné miesto
Konzument Konzument vyberávyberá zo skladu a konzumuje, ak je v sklade zo skladu a konzumuje, ak je v sklade nejaká položkanejaká položka
Riešenie bez kooperácie:Riešenie bez kooperácie:
Vlákno producent a konzumer sú Vlákno producent a konzumer sú synchronizovanésynchronizované monitorommonitorom asociovaným s objektom skladu: v každom asociovaným s objektom skladu: v každom okamihu je okamihu je iba jedeniba jeden z nich vo vnútri skladu z nich vo vnútri skladu
Ak sa sklad vyprázdni, konzument Ak sa sklad vyprázdni, konzument musí pravidelnemusí pravidelne zazerať do skladu, či je ešte stále prázdnyzazerať do skladu, či je ešte stále prázdny – – činnéčinné čakaniečakanie na príchod novej položky na príchod novej položky
1616
Kooperácia vlákienKooperácia vlákien
Podpora kooperácie Podpora kooperácie (elimin(elimináciáciaa činného čakania činného čakania na splnenie podmienkyna splnenie podmienky))::
wwaitait()() – – vláknovlákno v kritickej sekcii sa v kritickej sekcii sa vzdvzdáá monitora monitora dovtedy, kým od iného vlákna nepríjme notifikáciudovtedy, kým od iného vlákna nepríjme notifikáciu
nnotifyotify(), notifyAll()(), notifyAll() – vl – vlákno v kritickej sekcii ákno v kritickej sekcii oznámioznámi nejaknejakému čakajúcemu vláknu, resp. čakajúcim ému čakajúcemu vláknu, resp. čakajúcim vlvláknam, že môžu v kritickej sekcii pokračovaťáknam, že môžu v kritickej sekcii pokračovať
waitwait(), notify(), notifyAll()(), notify(), notifyAll() s sú inštančné metódy ú inštančné metódy objektu, s ktorým je asociovaný monitorobjektu, s ktorým je asociovaný monitor
1717
Algoritmus konzumentaAlgoritmus konzumenta
while (true) {
synchronized (sklad) {
// Kym niet v sklade ziadnej polozky
// cakame za notifikaciou
while (!sklad.hasItem())
sklad.wait();
// Skonzumujeme polozku
consume(sklad.getItem());
// Ak niekto (producent) caka za uvolnenim
// miesta v sklade, tak mu posleme notifikaciu
sklad.notify();
}
}
1818
SchSchéma fungovania monitorovéma fungovania monitorov
1919
Volatile premennéVolatile premenné
volatilevolatile označuje premenné, ktoré môžu byť označuje premenné, ktoré môžu byť modifikované viacerými vláknami a inštruuje modifikované viacerými vláknami a inštruuje procesor, aby vždy použil hodnotu „aktuálnu“ procesor, aby vždy použil hodnotu „aktuálnu“ hodnotu namiesto hodnoty cachovanej v hodnotu namiesto hodnoty cachovanej v registrochregistroch
public void doWork()
{
while (!shutdownRequested)
processing();
}
2020
Vlákna v JVMVlákna v JVM
““Green ThreadsGreen Threads” ”
do verzie 1.1 jediný mechanizmus riadenia vlákiendo verzie 1.1 jediný mechanizmus riadenia vlákien
kooperatkooperatívny multiívny multitaskingtasking
JVM JVM simulujesimuluje viacero vl viacero vlákien v jednom vlákne ákien v jednom vlákne
Od Od verzie verzie 1.2 využívanie vlákien OS1.2 využívanie vlákien OS
MonitoryMonitory::
InInštrukcie v štrukcie v bytebyte-code-code ((monitorenter, monitorexitmonitorenter, monitorexit))
Ku každému objektu je priradené počítadlo Ku každému objektu je priradené počítadlo počítajúce počet vstupov vlákna do kritickej sekcie počítajúce počet vstupov vlákna do kritickej sekcie asociovaného monitoraasociovaného monitora
2121
Ďalšie užitočné triedyĎalšie užitočné triedy
ThreadLocalThreadLocal – – objekt, ktorý objekt, ktorý pre kapre každé vlákno ždé vlákno uchováva špecifickú hodnotuuchováva špecifickú hodnotu
TimerTimer
vytvvytvára vlákno, do ktorého je možné vkladať úlohy ára vlákno, do ktorého je možné vkladať úlohy ako objekty triedy ako objekty triedy TimerTaskTimerTask
vykonanie úlohy je možné naplánovať na určitý čas, vykonanie úlohy je možné naplánovať na určitý čas, resp. periodické vykonávanieresp. periodické vykonávanie
SwingTimer, SwingWorkerSwingTimer, SwingWorker – mechanizmus na – mechanizmus na podporu konkurencie v rámci podporu konkurencie v rámci SwingSwing a a vykonvykonávania akcií v rámci ávania akcií v rámci Event Dispatch Event Dispatch ThreaduThreadu (jedin (jediný spôsob ako pracovať threadý spôsob ako pracovať thread--safety so safety so SwingSwing-om)-om)
2222
Java Java 1.5: Executor Framework1.5: Executor Framework
ProblProblém:ém: Ak potrebujeme vykonávať Ak potrebujeme vykonávať veľa veľa krkrátkychátkych súbežných úloh, tak vytvorenie vlákna súbežných úloh, tak vytvorenie vlákna sa stane drahou operáciousa stane drahou operáciou
Riešenie:Riešenie: Budeme udr Budeme udržiavať „žiavať „poolpool” vl” vlákien a ak ákien a ak príde nová úloha, tak použijeme nejaké voľné príde nová úloha, tak použijeme nejaké voľné vláknovlákno
ExecutorsExecutors: : tovtováreň Executorováreň Executorov
newSingleThreadExecutor()newSingleThreadExecutor()
newFixedThreadPool()newFixedThreadPool()
newCachedThreadPool()newCachedThreadPool()
newScheduledThreadPoolnewScheduledThreadPool()()
2323
public class WebServer {
static Executor pool = Executors.newFixedThreadPool(7);
public static void main(String[] args) {
ServerSocket socket = new ServerSocket(80);
while (true) {
final Socket connection = socket.accept();
Runnable r = new Runnable() {
public void run() {
handleRequest(connection);
}
};
pool.execute(r);
}
}
}
2424
Java 1.5: Callable, FutureJava 1.5: Callable, Future
ProblProblém:ém: neexistuje jednoduchý spôsob ako neexistuje jednoduchý spôsob ako vytvoriť súbežnú úlohu, ktorá vytvoriť súbežnú úlohu, ktorá vráti výsledokvráti výsledok iným iným vláknamvláknam
Riešenie: Riešenie:
ExecutorExecutor má metódu má metódu submitsubmit, ktorou ide odoslať na , ktorou ide odoslať na vykonanie úlohuvykonanie úlohu
Úloha je preprezentovaná ako implementácia Úloha je preprezentovaná ako implementácia rozhrania rozhrania CallableCallable<V><V> … met… metóda óda V callV call()()
Výsledkom volania Výsledkom volania submitsubmit je implementácia je implementácia rozhrania rozhrania FutureFuture<V><V>, ktor, ktoré poskytuje metódu é poskytuje metódu getget()() na zna získanie výsledku vykonania úlohyískanie výsledku vykonania úlohy
2525
Java 1.5: LepJava 1.5: Lepšia synchronizáciašia synchronizáciaProblém:Problém: systém monitorov je systém monitorov je obmedzenýobmedzený, , dovoľuje len hierarchické získavanie monitorov dovoľuje len hierarchické získavanie monitorov (z(zámkovámkov))
RieRiešenie:šenie:
Semaphore: acquireSemaphore: acquire/release/release
java.util.locksjava.util.locks: Lock, Condition, ReadWriteLock, : Lock, Condition, ReadWriteLock, ReentrantLock, ReentrantReadWriteLockReentrantLock, ReentrantReadWriteLock
LockLock: lock/unlock: lock/unlock
SynchronizovanSynchronizované kolekcie: é kolekcie: ArrayBlockingQueueArrayBlockingQueue
Atomické premennéAtomické premenné
2626
Java 1.5: LepJava 1.5: Lepšia koordináciašia koordinácia
CountDownLatchCountDownLatch: umožňuje pozastaviť vlákna, : umožňuje pozastaviť vlákna, kým sa nevykoná určitá množina operácií kým sa nevykoná určitá množina operácií (countDown, await)(countDown, await)
CyclicBarrierCyclicBarrier: umo: umožnuje pozastaviť vlákna, kým žnuje pozastaviť vlákna, kým zadaný počet vlákien nedosiahne definovanú zadaný počet vlákien nedosiahne definovanú bariéru bariéru (await)(await)
2727
Ďakujem za pozornosť.