Procházka na provázku

Podobné dokumenty
Programování v jazyku Java vlákna a procesy

Vlákna. První jednoduchý program s vlákny:

Vlákna. První jednoduchý program s vlákny:

30. Vlákna, jejich atributy, metody, organizace a stavy. Možnosti synchronizace. (A7B36PVJ)

VIII. Seminář Java VIII p.1/36

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

JAVA V Vlákna Java, zimní semestr

Vláknové programování část V

Vlákno odlehčený proces kód vlákna, zásobník privátní ostatní sdíleno s dalšími vlákny téhož procesu

Příklad aplikace Klient/Server s Boss/Worker modelem (informativní)

Abstraktní datové typy: zásobník

Programovací jazyky s podporou vláken Java

Seznamy a iterátory. Kolekce obecně. Rozhraní kolekce. Procházení kolekcí

Z. Kotala, P. Toman: Java ( Obsah )

4. ZÁKLADNÍ POJMY Z OBJEKTOVĚ ORIENTOVANÉHO PROGRAMOVÁNÍ

Programování v Javě I. Únor 2009

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

typová konverze typová inference

JAVA. Krátke poznámky:

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

TŘÍDY POKRAČOVÁNÍ. Události pokračování. Příklad. public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e);

Programování v Javě I. Leden 2008

Vícevláknové aplikace

Konstruktory a destruktory

JAVA V jar Java, zimní semestr

IRAE 07/08 Přednáška č. 7. Začátek (head)

RMI Remote Method Invocation

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

Algoritmizace a programování

Správa paměti. Karel Richta a kol. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze Karel Richta, 2016

Multithreading vícevláknovost

Struktura programu v době běhu

Java Výjimky Java, zimní semestr

C++ 0x aka C++11. Základním kamenem je třída std::thread

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

Stromy. Příklady. Rekurzivní datové struktury. Základní pojmy

KTE / ZPE Informační technologie

Teoretické minimum z PJV

Cvičení 9 - Monitory. monitor m; var proměnné... procedure p; begin... end; begin inicializace; end;

Předmluva k aktuálnímu vydání Úvod k prvnímu vydání z roku Typografické a syntaktické konvence... 20

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Class loader. každá třída (java.lang.class) obsahuje referenci na svůj class loader. Implementace class loaderu

1. Téma 12 - Textové soubory a výjimky

Statické proměnné a metody. Tomáš Pitner, upravil Marek Šabo

Seminář Java II p.1/43

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Řada programovacích jazyků nabízí prostředky pro řešení meziprocesové komunikace jako je synchronizace a řízení přístupu do kritické sekce.

PREPROCESOR POKRAČOVÁNÍ

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Úvod do programovacích jazyků (Java)

8 Třídy, objekty, metody, předávání argumentů metod

ALGORITMIZACE 2010/03 STROMY, BINÁRNÍ STROMY VZTAH STROMŮ A REKURZE ZÁSOBNÍK IMPLEMENTUJE REKURZI PROHLEDÁVÁNÍ S NÁVRATEM (BACKTRACK)

OMO. 4 - Creational design patterns A. Singleton Simple Factory Factory Method Abstract Factory Prototype Builder IoC

ALGORITMIZACE 2010/03 STROMY, BINÁRNÍ STROMY VZTAH STROMŮ A REKURZE ZÁSOBNÍK IMPLEMENTUJE REKURZI PROHLEDÁVÁNÍ S NÁVRATEM (BACKTRACK)

PŘETĚŽOVÁNÍ OPERÁTORŮ

součet cvičení celkem. známka. Úloha č.: max. bodů: skut. bodů:

Algoritmizace a programování

Typický prvek kolekce pro české řazení

Procesy a vlákna - synchronizace

ZOS 9. cvičení, ukázky kódu. Pavel Bžoch

Soubor jako posloupnost bytů

Generické programování

Management procesu I Mgr. Josef Horálek

boolean hasnext() Object next() void remove() Kolekce

Operační systémy. Přednáška 4: Komunikace mezi procesy

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

Datové struktury obsah přednášky 1. Úvod 2. Třídy Type-wrapper (obalový typ) pro primitivní typy automatické převody 3. Automatické převody mezi

Abstraktní třída a rozhraní

Obsah přednášky 9. Skrývání informací. Skrývání informací. Zapouzdření. Skrývání informací. Základy programování (IZAPR, IZKPR) Přednáška 9

Pokročilé programování na platformě Java. Úvod

Java Enum Java, zimní semestr ,2017 1

7. Datové typy v Javě

20. Projekt Domácí mediotéka

Pavel Procházka. 3. prosince 2014

public class Karel { private int position; public boolean issmiling; public int getposition() { return position;

Více o konstruktorech a destruktorech

Synchronizace Mgr. Josef Horálek

1. Programování proti rozhraní

Java - výjimky. private void vstup() throws IOException {... }

Iterator & for cyklus

Vytváření a použití knihoven tříd

Služba ve Windows. Služba (service) je program

Principy operačních systémů. Lekce 6: Synchronizace procesů

IRAE 07/08 Přednáška č. 2. atr1 atr2. atr1 atr2 -33

5 Rekurze a zásobník. Rekurzivní volání metody

Seminář Java IV p.1/38

Úvod do programovacích jazyků (Java)

Příklad : String txt1 = new String( Ahoj vsichni! ); //vytvoří instanci třídy String a přiřadí ji vnitřní hodnotu Ahoj vsichni!

Stromy. Karel Richta a kol. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze Karel Richta a kol.

Datové struktury. alg12 1

Java a XML. 10/26/09 1/7 Java a XML

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Počítačové laboratoře bez tajemství aneb naučme se učit algoritmizaci a programování s využitím robotů CZ.1.07/1.3.12/

Zápis programu v jazyce C#

Otázka 31 - Y36PJV. PDF created with pdffactory trial version Zadání. Procesy a vlákna. Vlákna. Proces. Vlákno.

Výčtový typ strana 67

JSR tutorial 2 Transformace v JSR-184

Transkript:

Procházka na provázku Program s mnoha metodami připomíná knósský labyrint s mnoha sály, jimiž se protlouká statečný Threadeus, jemuž pro šťastný návrat chytrá Ariadna dala klubíčko. Threadeus pokaždé při vstupu do metody vlákno rozvíjí a při návratu z metody svíjí. V metodách Threadeus provádí příkazy. V jávském labyrintu však může pobíhat najednou i více hrdinů a dokonce i rekurzivně neb je multithreadový. ( Leč v jednom procesoru se v daném okamžiku pohybuje nanejvýš jeden tak jako v člověče nezlob se. ) Každý Threadeus má svoje vlákno - druhé konce třímá JVM v roli Ariadny, aby v případě nehody (...Exception ) mohla ony smolaře v labyrintu najít a z té šlamastiky vytáhnout. Totiž ani padlí gerojové tam nesmějí zůstat. V labyrintu se mohou potulovat také démoni služební džinové, kteří se však vytratí, není-li tam již žádný živý opravdový hrdina. Také démoni jsou vláknem připoutáni k JVM. PJV06 1

isalive( )= new false true start( ) completed interrupt( ) I/O end acquires lock Threadeovy osudy runnable state CPU scheduler interrupt ( ) blocked state yield( ) synchron. sleep( ) join( ) I/O start running state interrupt( ) sets flag only run( ) { wait(...) must have lock and then releases lock dead lock state notify( ) interrupt( ) wait state lock pool wait pool PJV06 2

Přidělováníčasu JVM scheduler přiděluje CPU čas nespecifikovaným způsobem některému vláknu s nejvyšší prioritou, pokud ono je ve stavu runnable. MAX priority 10 T6 T8 CPU time scheduler NORM MIN 5 1 T7 T2 T5 T3 T4 T10 T9 T6 T1 state: new runnable running blocked dead PJV06 3

Vlákno = thread = lightweight process = task... Vlákno není program je to jakýsi výpočtář, tj. objekt vykonávajícíčinnost. K provedení výpočtu je nezbytný alespoň jeden výpočtář, který má: k dispozici program tedy předpis postupu ( metody ), přístupná data což jsou atributy tříd, objektů, parametry, proměnné, čas na práci. Vlákno si musí dynamicky pamatovat: 1. v které metodě se právě nalézá a kam se pak vrátit, 2. své lokální proměnné ( obé je v aktivačním záznamu na zásobníku ), 3. adresu aktuálního příkazu v aktuální metodě ( program counter ). Výpočet končí, skončí-li všechna nedémonická vlákna. Otázka jak je vlákno dlouhé, není nesmyslná: jeho délka se dá chápat jako momentální počet aktivačních záznamů na zásobníku. PJV06 4

Thread a Runnable JVM scheduler dodává CPU čas tím, že zavolá metodu run() objektů typu java.lang.thread, zařazených do prioritních front jsou-li ve stavu runnable-running. V těle metody public void run( ) se definuje požadované chování vlákna lze volat též metody libovolného objektu či třídy. Interfejs java.lang.runnable obsahuje pouze metodu: public void run(); Thread je konkrétní třída implementující Runnable skoro prázdnou, metodou umožňující předat řízení metodě run v cílovému objektu takto: public void run( ) { if ( target!= null ) target.run(); V potomcích Threadu se metoda run( ) přepisuje na neprázdnou definující požadovanou činnost vlákna. PJV06 5

Metoda run( ) Metoda public void run( ) { tedy definuje, co má vlákno dělat. Volá ji JVM a nikoli programátor - ten pouze vlákno odstartuje metodou start( ), čímž se vlákno zařadí do fronty a oživí - isalive( ) vrací true. Metoda run( ) typicky obsahuje cyklus, který probíhá, pokud jiné vlákno nenastaví condition na false. Tak je zajištěno, že vlákno dokoná definovaným způsobem ( zavrženou metodou stop( ) nikoli ). class X implements Runnable { boolean condition = true; // počáteční nastavení public void run( ) { while ( condition ) {... // požadovanáčinnost // smrtící závorka PJV06 6

Konstruktory Thread má osm přetížených konstruktorů s různými kombinacemi těchto parametrů: Runnable target - přesměrování dodávky CPU do určeného objektu, který implementuje interfejs Runnable. String name - jméno vlákna ( chybí-li, dosadí se systematické jméno ). ThreadGroup group - přiřazení vlákna do skupiny, změna nemožná. Skupinu vláken lze ovládat najednou. long stacksize - nastavení velikosti zásobníku. PJV06 7

Statické metody Thread currentthread( ) - odkaz k běžnému vláknu. int activecount( ) - počet aktivních vláken ve skupině běžného vlákna. void dumpstack( ) - výpis zásobníku. boolean holdslock( Object o ) - test zda vlákno má zámek objektu. boolean interrupted( ) - bylo toto vlákno přerušeno? A výmaz příznaku. native void sleep( long msec ) throws InterruptedException dočasné uspání. Vyhazuje výjimku při předčasném probuzením jiným vláknem. void yield( ) - vlákno přejde ze stavu running do runnable, tj. zřekne se zbytku momentálního přídělu času. int enumerate ( Thread[ ] tarr ) do určeného pole zkopíruje všechna aktivní vlákna skupiny běžného vlákna a jejích podskupin. PJV06 8

Nestatické metody void run( ) - definice funkcionality. void start( ) - aktivace, tj. oživení ( mrtvé vlákno nelze oživit ). boolean isalive( ) - test života. int getname( ) / void setname( String name ) - getter/setter jména. int getpriority( ) / void setpriority( int priority ) - getter/setter priority. Thread.State getstate( ) stav pro monitoring ne pro synchonizaci. ThreadGroup getthreadgroup( ) skupina do které vlákno patří. boolean isdaemon( ) - test démona. void setdaemon( boolean on ) - nastavení démona/nedémona. void interrupt( ) - přerušení vlákna. boolean isinterrupted( ) - bylo ono vlákno přerušeno? Příznak nezměněn. void join( ) throws InterruptedException -čekání na konec jiného vlákna. void join( long msec ) throws InterruptedException s maximem čekání. Všeobecné, zastaralé a méně důležité metody zde nejsou uvedeny. Nedémon defaultně vytváří nedémona, démon démona. Démoničnost je nastavitelná jen před spuštěním dotyčného vlákna. PJV06 9

Způsoby použití S vlákny lze pracovat dvojím způsobem: 1. Definovat potomka třídy Thread, v něm přepsat metodu run( ) pro požadovanou funkcionalitu, zkonstruovat objekt a ten aktivovat zděděnou metodou start( ). Toto řešení se hodí jen pro velmi jednoduché případy. 2. Definovat jakoukoli třídu implementující interfejs Runnable a do ní přepsat metodu run( ) pro požadovanou funkcionalitu. Zkonstruovat příslušný objekt. Zkonstruovat objekt Thread s parametrem Runnable odkazující na příslušný objekt. Nakonec odstartovat objekt Thread. Toto řešení je obecnější, běžící objekt může být složitý, neboť může výhodně dědit od bohaté třídy. PJV06 10

První způsob: Tik class Tik extends Thread { public void run( ) { // přepsaná metoda Threadu try { while( true ) { System.out.println( Tik ); sleep( 1000 ); // static method catch( InterruptedException ex ) { spuštění zkráceně: new Tik( ).start( ); spuštění rozepsaně: Tik t = new Tik( ); t.start( ); Protože Tik je Thread, startem se zařadí do fronty na CPU čas. PJV06 11

Druhý způsob: Tak class Tak extends HodinkySVodotryskem implements Runnable { public void run( ) { // přepsaná metoda Runnable try { while( true ) { System.out.println( Tak ); Thread.sleep( 1000 ); // static method catch( InterruptedException ex ) { spuštění zkráceně: new Thread( new Tak( ) ). start( ); spuštění rozepsaně: Runnable r = new Tak( ); new Thread( r ). start( ); Tak není Thread, avšak má metodu run, kterou zavolá nepřepsaná metoda Threadu, neboť Tak je její target. PJV06 12

Tik versus Tak java.lang. Object CPU time priority queue Tik Thread call return java.lang. Thread java.lang. Runnable Tak run() { run() ; Tik Tak run() { run() { class interface extends implements Tak object PJV06 13

Interakce vláken Vlákna mohou běžet na sobě nezávisle, mohou se vzájemně hledat, testovat, [ne]koordinovaně ovlivňovat anebo mohou spolupracovat. Metody pro: hledání: currentthread( ), activecount( ), getthreadgroup( ),... testování: isalive( ), isdaemon( ), interrupted( ), isinterrupted( ),... ovlivňování: start( ), nastavení proměnných, interrupt( ), setpriority( ),... navazování: join( ) spolupráci: wait( ), notify( ), notifyall( ) tyto metody vyžadují synchronizaci pomocí synchronized. PJV06 14

Interupt Metoda t.interrupt( ) sama nezaručuje zastavení vlákna t - záleží na stavu vlákna t. running : žádná vyjímka se nevyhodí, jen mu nastaví jeho příznak přerušení (flag). Je na tomto aby si svůj flag evetuálně zkontroloval a něco udělal. Pokud později přejde do stavu waiting nebo sleeping, předtím než metoda interrupted( ) příznak shodí, vyhodí se InterruptedException a příznak se shodí. waiting/sleeping : Vlákno přejde do runnable stavu a jakmile poběží vyhodí se InterruptedException. Příznak přerušení není nastaven. runnable : nic se neděje do té doby než přejde do running stavu dále viz první bod. PJV06 15

Join Metoda t.join( timeout ) blokuje běžné vlákno pokud je vlákno t živé, nejdéle však po dobu timeout. Je-li timeout == 0 je doba nekonečná. Metoda t.join( ) je ekvivalentní t.join(0). To umožňuje běžnému vláknu vyčkat a pak navázat na výsledky činnosti dokončení práce vlákna t. Neodstartované vlákno t je neživé a tedy neblokuje běžné. Na ukončení vlákna může čekat více vláken. Vlákna se nijak vzájemně nenavazují ( tj. nesloučí se v nějaké jediné - každé samostatně doběhne ), navazuje se jejich práce. PJV06 16

Pilný strýc a líný synovec Vlákno-synovec lajdá (je blokován) do doby, než vlákno-strýc dokončí svůj úkol (vydělat sto milionů) -čili až zemře. Dědictví si však dlouho neužije. Synovec může zjistit strýcův stav metodou isalive( ). Je-li nedočkavý, zavolá metodu join( timeout ) - leč získá jen část peněz. public class Nephew { static Uncle u = new Uncle( ); public static void main( String[ ] args ) throws InterruptedException { u.join( ); // blocked System.out.println( u.money ); // heritage class Uncle extends Thread { int money = 0; public Uncle( ) { this.start( ); public void run( ) { while ( ( ++money ) < 100000000 ); // work PJV06 17

Nesynchronizace v hanebné bance public class Test { public static void main( String[ ] args ) { new Clerk( ).start( ); new Clerk( ).start( ); for ( int i=1; true; i++ ) System.out.println( i+ ".:" + Accounts.dump( ) ) ; class Accounts { static long a1=0, a2 = 1000; static void move( int x ) { a1 -= x; a2 += x; // zdroj problému static String dump( ) { return a1+ " + " +a2+ " = " +(a1+a2); class Clerk extends Thread { public void run( ) { while ( true ) Accounts.move( ( int ) ( ( Math.random( ) - 0.5 ) *100 ) ); PJV06 18

Synchronizace Synchronizace brání vstupu více vláken do tzv. kritických sekcí, aby jejich nekoordinovanáčinnost nezpůsobila chaos v hodnotách atributů. ( Obdobou kritické sekce je autoblok na železnici. ) Klíčové slovo synchronized u metody či bloku definuje kritickou sekci. Kritických sekcí může být více a mohou být i do sebe vložené. Mají být co nejkratší, aby nesnižovaly průchodnost programu. Každý objekt má jediný zámek ( intrinsic lock, monitor lockči též monitor ). Vlákno, které zámek získá, vstoupí do kritické sekce a zamkne objekt, po jejím opuštění se zámek vrátí objektu, čímž se objekt odemkne. Vlákno může získat více zámků od různých objektů. Vlákno bez patřičného zámku ke kritické sekci do ní vstoupit nemůže a je přeřazeno ze stavu running do čekárny lock poolu. Vrácený zámek JVM přidělí nedeterministicky některému příslušnému vláknu z lock poolu a přeřadí ho do stavu runnable. PJV06 19

Synchronizace class X {... synchronized... method1 (... ) { // Synchronizovaná metoda method2 (... ) { // Nesynchronizovaná metoda synchronized( o1 ) { // Synchronizované bloky synchronized( o2 ) { // o1, o2 jsou reference k nějakým objektům // nebo this nebo Z.class anebo k poli Atributy jejichž hodnoty se mění mají být private. Statické synchronizované metody využívají zámek třídy. Konstruktory a inicializátory provádí právě jedno vlákno. PJV06 20

Synchonizace v solidní bance Solidní banka zjedná nápravu takto: class Accounts { static private long a1=0, a2 = 1000; static synchronized void move( int x ) { a1 -= x; a2 += x; static String dump( ) { return a1+ " + " +a2+ " = " +(a1+a2); // OK anebo takto: class Accounts { static private long a1=0, a2 = 1000; static void move( int x ) { synchronized ( Accounts.class ) { a1 -= x; a2 += x; // OK static String dump( ) { return a1+ " + " +a2+ " = " +(a1+a2); Jak patrno v obou případech se (nevhodně) využívá zámek třídy Accounts. PJV06 21

Spolupráce Vlákna spolupracující na nějakém objektu, musejí být koordinována tak, aby nepatřičně nezasahovala do společně přístupných dat. Příkladem je PC-problém ( Producer Consumer ): Producenti se snaží dodat nějaké objekty do společného skladu. Konzumenti se snaží objekty ze společného skladu odebrat. Sklad má určitou kapacitu a je-li: - plný, producenti čekají na volné místo. - prázdný, konzumenti čekají na dodávku. Žádný objekt se nesmí ztratit. Tentýž objekt nesmí být odebrán dvakrát. Producenti ani konzumenti se navzájem neznají Producenti a konzumenti musejí být upozorňováni o změnách stavu skladu. Sklad musí být dobře střežen: důležité proměnné musejí být private. Přístup k nim je možný jen přes synchronizované metody. Přístup do skladu má vždy pouze jeden producent anebo konzument. PJV06 22

PC - problém Producers Store Consumers lock synchronized put synchronized get PJV06 23

Metody wait a notify Koordinovaný přístup ke sdíleným datům se zajišťuje jednak všeobecnými finálními metodami wait a notify a jednak čekárnami wait pool a lock pool. Volat wait a notify může jen vlákno vlastnící zámek k objektu, tj. jen uvnitř kritické sekce, jinak dojde k IllegalMonitorStateException. Čekáním vlákna ve wait poolu na změnu: - wait( ) - vlákno čeká až... - wait( long timeout ) čeká až..., leččeká nejdéle zadanou dobu. Obě metody wait odemykají objekt a vracejí zámek. Vlákno se převede z wait do lock poolu též zavoláním metody interrupt( ), přičemž se vyhodí výjimka InterruptedException. Upozorněním jiného vlákna, že došlo ke změně podmínek. Vlákno (či vlákna) se z wait do lock poolu se převede metodou: - notify( ) - JVM nedeterministicky převede jedno vlákno. - notifyall( ) - JVM převede všechna vlákna. Vlákna v lock poolu čekají na přidělení zámků k příslušným objektům. PJV06 24

public class PCProblem { Producer Consumer Problem public static void main(string[ ] args) throws Exception { Box b = new Box( ); Producer p = new Producer(b); p.start( ); Consumer c = new Consumer(b); c.start( ); p.join( ); c.join( ); b.print( "END" ); PJV06 25

Producer Consumer Problem class Box { // Box for one object only private Object x; public void print( String r ) { System.out.println( r+" Box has "+x ); synchronized void put( Object z ) { // z must not be null while ( x! = null ) try { wait( ); catch ( InterruptedException ex ) { notifyall( ); x = z; print( "PUT" ); synchronized Object get( ) { while ( x == null ) try { wait( ); catch ( InterruptedException ex ) { notifyall( ); Object z = x; x=null; print( "GET" ); return z; PJV06 26

Producer Consumer Problem class Producer extends Thread { Box b; Producer( Box b ) { this.b=b; public void run( ) { for ( int i = 0; i < 10; i++ ) { b.put( new Integer( i ) ); try { sleep( ( int )( Math.random( )*1000 ) ); catch ( InterruptedException ex ) { PJV06 27

Producer Consumer Problem class Consumer extends Thread { Box b; Consumer( Box b ) { this.b=b; public void run( ) { for ( int i = 0; i < 10; i++ ) { System.out.println( ( Integer ) b.get( ) ); try { sleep( ( int ) ( Math.random( )*1000 ) ); catch ( InterruptedException ex ) { PJV06 28

Uvíznutí (deadlock) Dva chudí lešetínští kováři mají jedno společné nářadí: kladivo a kleště. Nedohodnou-li se, dojde časem k zlobně umrtvujícímu nicnedělání, tzv. deadlockučili smrtelnému zaklesnutí. Přihodí se to takto: První uchopil kladivo a potřebuje ještě kleště. Mezitím však druhý uchopil kleště a čeká až bude kladivo volné. Nikdo to za ně nevyřeší a tak oba čekají a čekají... čímž živnosti uvíznou a oba ještě více zchudnou - a šafářovic Andulka se nedočká. Přitom stačí rozumná dohoda - budeš-li potřebovat oba nástroje: Nejdříve uchop kladivo a teprve pak sháněj kleště. Pracuj. Pak nejdříve pusť kleště, potom kladivo. Ta zaručuje momentálnímu držiteli kladiva, že kleště budou časem volné. Kovářů může být ve městě i více. PJV06 29

Proti uvíznutí Programátor znemožní uvíznutí takto: synchronized ( hammer ) { synchronized ( tongs ) {... // work Více nářadí lze vložit do synchronizované kolekce či do pole. ( Pole je svou podstatou synchronizovaný objekt. ) private Collection tools = new Vector( ); tools.add( hammer ); tools.add( tongs ); tools.add(...); // fill tools synchronized ( tools ) { Object x = tools.get(...);... // work PJV06 30

Skupiny vláken JVM odstartovaná vlákna umístí jako listy stromu, jehož kořen a vnitřní uzly jsou skupiny vláken typu ThreadGroup. Mrtvá vlákna z tohoto stromu JVM odstraní. Třída ThreadGroup nabízí metody: ThreadGroup( ThreadGroup parent, String name ) konstruktor. int activecount( ) odhad počtu vláken ve skupině. int activegroupcount( ) odhad počtu skupin ve skupině. int enumerate( Thread[ ] ) výčet vláken ve skupině. int enumerate( ThreadGroup[ ] ) výčet skupin vláken ve skupině. ThreadGroup getparent( ) reference k nadskupině. boolean parentof( ThreadGroup g ) test příslušnosti k podstromu g. void list( ) výpis skupiny. void interrupt( ) přerušení všech vláken podstromu. boolean isdaemon( ) test zda je skupina démonická. void setdaemon( boolean on ) démonizace všech vláken. void setmaxpriority( int pri ) nastavení pro dalšíčleny skupiny. void destroy( ) zrušení prázdného podstromu. PJV06 31

Časové spouštění úloh umožňují třídy java.util.timer a abstraktní java.util.timertask. Timer( ) konstruktor. Timer( boolean isdaemon ) konstruktor pro démona. void schedule(... ) naplánuje spuštění úkolu. void scheduleatfixedrate(... ) spouštění s pevným intervalem. - tyto metody mají parametry: TimerTask task naplánovaný úkol. Date firsttime datum a čas prvního spuštění. long delay zpoždění pro první spuštění. long period perioda dalších spuštění. void cancel( ) ukončíčinnost objektu i naplánované úkoly. Uplynul-li již moment spuštění, spustí se ihned. PJV06 32

Časové spouštění úloh Abstraktní třída java.util.timertask má: protected TimerTask( ) konstruktor. public void cancel( ) ukončí naplánovaný úkol. public long scheduledexecutiontime( ) čas posledního spuštění. public abstract void run( ) definice činnosti. Timer t = new Timer( ); t.schedule( new TTA( ), 10000 ); t.scheduleatfixedrate( new TTB( ), 5000, 500 ); class TTA extends TimerTask{ public void run( ) { System.out.println( A ); class TTB extends TimerTask{ public void run( ) { System.out.println( B ); PJV06 33

Jak JVM spouští aplikaci Při spuštění java T aa bb ccc systémové vlákno vytvoří ThreadGroup se jménem main a v ní Thread se jménem main s prioritou 5 odstartuje ho. Vlákno main projde postupně všemi statickými inicializátory ( nedojde-li k neodchycené výjimce a tudíž k ExceptionInInitializerError a ukončení chodu ). Následně projde do metody T.main. class... extends Thread { public void run( ) { try { // call all static initializers // call T.main(... ) catch ( Throwable ex ) { ex.printstacktrace(); PJV06 34