Ciclul de Viata Al Unui Fir de Executie

download Ciclul de Viata Al Unui Fir de Executie

of 6

Transcript of Ciclul de Viata Al Unui Fir de Executie

  • 7/25/2019 Ciclul de Viata Al Unui Fir de Executie

    1/6

    Ciclul de viata al unui fir de executie

    Fiecare fir de executie are propriul sau ciclu de viata : este creat, devine activ prin lansarea sa n executie

    si, la un moment dat, se termina. In continuare vom vedea mai ndeaproape starile n care se poate gasi un

    fir de executie. Diagrama de mai jos ilustreaza generic aceste stari precum si metodele care provoaca

    tranzitia dintr-o stare n alta:

    Asadar, un fir de

    executie se poate gasi

    n una din

    urmatoarele patru

    stari:

    1. e! "#read

    $. %unna&le

    '. ot %unna&le

    (. Dead

    Starea "New Thread"

    )n fir de executie se gaseste n aceasta stare imediat dupa crearea sa, cu alte cuvinte dupa instantierea

    unui o&iect din clasa Threadsau dintr-o su&clasa a sa.Thread counterThread = new Thread ( this );//counterThread se gaseste in starea New Thread

    In aceasta stare firul de executie este *vid*, el nu are alocate nici un fel de resurse sistem si singura

    operatiune pe care o putem executa asupra lui este lansarea n executie, prin metoda start. Apelul

    oricarei alte metode n afara de startnu are nici un sens si va provoca o exceptie de tipul

    IllegalThreadStateException.

    Starea "Runnable"

    Dupa apelul metodei startun fir de executie va trece n starea *%unna&le*, adica se gaseste n executie.counterThread.start();//counterThread se gaseste in starea Runnable

    +etoda startrealizea urmatoarele operatiuni necesare rularii firului de executie:

    aloca resursele sistem necesare

    planifica firul de executie la ) pentru a fi lansat

    apeleaza metoda run a o&iectului reprezentat de firul de executie

    )n fir de executie aflat n starea %unna&le nu nseamna neaparat ca acesta se gaseste efectiv n executie,

    adica instructiunile sale sunt interpretate de procesor. Acest lucru se ntmpla din cauza ca majoritatea

    calculatoarelor au un singur procesor iar acesta nu poate rula simultan toate firele de executie care se

    gasesc n starea %unna&le. entru a rezolva aceasta pro&lema interpretorul /ava implementeaza o

    planificare care sa partajeze dinamic si corect procesorul ntre toate firele de executie care sunt n starea

    %unna&le. Asadar, un fir de executie care *ruleaza* poate sa-si astepte de fapt rndul la procesor.

    Starea "Not Runnable"

  • 7/25/2019 Ciclul de Viata Al Unui Fir de Executie

    2/6

    )n fir de executie ajunge n acesata stare n una din urmatoarele situatii:

    este *adormit* prin apelul metodei sleep.

    a apelat metoda wait, asteaptnd ca o anumita conditie sa fie satisfacuta

    este &locat ntr-o operatie de intrare0iesire

    "Adormirea" unui fir de executie

    +etoda sleepeste o metoda statica a clasei Threadcare provoaca o pauza n timpul rularii firului curent

    aflat n executie, cu alte cuvinte l *adoarme* pentru un timp specificat. ungimea acestei pauze este

    specificata n milisecunde si c#iar nanosecunde.public static oid sleep( long !illis )

    throws InterruptedExceptionpublic static oid sleep( long !illis" int nanos )

    throws InterruptedException

    Intruct poate provoca exceptii de tipul InterruptedException apelul acestei metode se face ntr-un &loc

    de tip tr#$cacth: tr# %Thread.sleep(&''');//ace paua de o secunda

    * catch (InterruptedException e) %. . .

    *

    2&servati ca metoda fiind statica apelul ei nu se face pentru o instanta anume a clasei Thread. Acest lucru

    este foarte normal deoarece, la un moment dat, un singur fir este n executie si doar pentru acesta are sens

    *adormirea* sa.

    In intervalul n care un fir de executie *doarme*, acesta nu va fi execut c#iar daca procesorul devine

    disponi&il. Dupa expirarea acestui interval firul revine n starea %unna&le, iar daca procesourul este n

    continuare disponi&il si contiunua executia.entru fiecare tip de intrare n starea *ot %unna&le*, exista o secventa specifica de iesire din starea

    repectiva, care readuce firul de executie n starea %unna&le. Acestea sunt:

    Daca un fir de executie a fost *adormit*, atunci el devine %unna&le doar dupa scurgerea

    intervalului de timp specificat de instructiunea sleep.

    Daca un fir de executie asteapta o anumita conditie, atunci un alt o&iect tre&uie sa l informeze

    daca acea conditie este ndeplinita sau nu3 acest lucru se realizeaza prin instructiunile noti#saunoti#+ll

    Daca un fir de executie este &locat ntr-o operatiune de intrare0iesire atunci el redevine %unna&le

    atunci cnd acea operatiune s-a terminat.

    Starea "Dead"

    4ste starea n care ajunge un fir de executie la terminarea sa. )n fir de executie nu poate fi oprit din

    program printr-o anumita metoda, ci tre&uie sa se termine n mod natural la terminarea metodei runpe

    care o executa. 5pre deose&ire de versiunile curente ale lim&ajului /ava, n versiunea 1.6 exista metoda

    stopa clasei Threadcare termina fortat un fir de executie, nsa ea a fost eliminata din motive de

    securitate.

    Asadar, un fir de executie tre&uie sa-si *aranjeze* singur propria sa *moarte*.

    Terminarea unui fir de executie

    Dupa cum am vazut, un fir de executie nu poate fi terminat fortat de catre program ci tre&uie sa-si

    *aranjeze* singur terminarea sa. Acest lucru poate fi realizat n doua modalitati:

  • 7/25/2019 Ciclul de Viata Al Unui Fir de Executie

    3/6

    rin scrierea unor metode runcare sa-si termine executia n mod natural3 la terminarea metodei

    runse va termina automat si firul de executie, acesta intrnd n starea Dead. Acesta este cazul din

    exemplul considerat anterior: public oid run() %

    or(int i = ro!; i ,= to; i -= step)

    S#ste!.out.print(i - ); *

    Dupa afisarea numerelor din intervalul specificat metoda se termina si odata cu ea si firul de

    executie repsectiv.

    rin folosirea unei varia&ile de terminare. In cazul cnd metoda run tre&uie sa execute o &ucla

    infinita atunci aceasta tre&uie controlata si printr-o varia&ila care sa opreasca aceasta &ucla atunci

    cnd dorim ca firul de executie sa se termine. )zual, aceasta este o varia&ila mem&ra a clasei care

    descrie firul de executie care fie este pu&lica, fie este asociata cu o metoda care i sc#im&a

    valoarea.

    5a consideram exemplul unui fir de executie care tre&uie sa numere secundele scurse pna la apasarea

    tastei 4nter. 7om scrie mai nti programul folosind metoda stop:

    Terminarea unui fir de executie folosind metoda "nvechita" stop

    i!port aa.io.0;public class TestThread %

    public static oid !ain(String args12) throws I3Exception %4ait5e# thread = new 4ait5e#();thread.start();S#ste!.in.read(); //astept apasarea tastei Enterthread.stop(); //opresc irul de executieS#ste!.out.println(S$au scurs - thread.sec - secunde);

    **class 4ait5e# extends Thread %

    public int sec = ';public oid run() %

    while (true) %tr# %

    Thread.sleep(&'''); //paue de o secundasec --; //s$a !ai scurs o secunda

    * catch(InterruptedException e)%**

    **

    2&servam ca metoda runnu se termina natural, ea ruleaza la infinit asteptnd sa fie terminata fortat. Acest

    lucru l-am realizat aici cu metoda stop. Aceasta metoda este nsa *nvec#ita* 8deprecated9 iar la

    compilarea programului vom o&tine un mesaj de avertizare n acest sens. utem evita metoda stopprin

    folosirea unei varia&ile de terminare.

    Terminarea unui fir de executie folosind o variabila de terminare

    i!port aa.io.0;public class TestThread %

    public static oid !ain(String args12) throws I3Exception %

  • 7/25/2019 Ciclul de Viata Al Unui Fir de Executie

    4/6

    4ait5e# thread = new 4ait5e#();thread.start();S#ste!.in.read(); //astept apasarea tastei Enterthread.running = alse;S#ste!.out.println(S$au scurs - thread.sec - secunde);

    *

    *

    class 4ait5e# extends Thread %public int sec = ';public boolean running = true; //ariabila de ter!inarepublic oid run() %

    while ( running ) %tr# %

    Thread.sleep(&''');sec --;

    * catch(InterruptedException e)%**

    *

    *

    Metoda isAlive

    Aceasta metoda este folosita pentru a vedea daca un fir de executie a fost pornit si nu s-a terminat nca.

    +etoda returneaza:

    true - daca firul este n una din starile %unna&le sau ot %unna&le

    false - daca firul este n una din starile e! "#read sau Dead

    Intre starile %unna&le sau ot %unna&le, repectiv e! "#read sau Dead nu se poate face nici o

    diferentiere.

    4ait5e# thread = new 4ait5e#();// is+lie retuneaa alse (starea este New Thread)

    thread.start();// is+lie retuneaa true (starea este Runnable)

    S#ste!.in.read();

    thread.running = alse;// is+lie retuneaa alse (starea este 6ead)

    u este necesara distrugerea explicita a unui fir de executie. 5istemul /ava de colectare a gunoiului se

    ocupa de acest lucru. 4l poate fi fortat sa dezaloce resuresele alocate unui t#read prin atri&uirea cu null a

    varia&ilei care referea instanta firului de executie: !#Thread = null .

    Stabilirea prioritatilor de executie

    +ajoritatea calculatoarelor au un sigur procesor, ceea ce nseamna ca firele de executie tre&uie sa-si

    mparta accesul la acel procesor. 4xecutia ntr-o anumita ordine a mai multor fire de executie pe un singur

    procesor se numeste planificare 8sc#eduling9. 5istemul /ava de executie a programelor implementeaza un

    algoritm simplu, determinist de planificare, cunoscut su& numele de planificare cu prioritati fixate.

    Fiecare fir de executie /ava primeste la crearea sa o anumita prioritate. 2 prioritate este de fapt un numar

    ntreg cu valori cuprinse ntre +I%I2%I"; si +A

  • 7/25/2019 Ciclul de Viata Al Unui Fir de Executie

    5/6

    public static inal int N3R789RI3RIT: $ prioritatea i!plicitapublic static inal int 7+89RI3RIT: $ prioritatea !axi!a

    5c#im&area ulterioara a prioritatii unui fir de executie se realizeaza cu metoda set9riorit#a clasei

    Thread.

    lanificatorul /ava lucreaza n modul urmator : daca la un moment dat sunt mai multe fire de executie n

    starea %unna&le, adica sunt pregatite pentru a fi executate, planificatorul l va alege pe cel cu prioritateacea mai mare pentru a-l executa. Doar cnd firul de executie cu prioritate maxima se termina sau este

    suspendat din diverse motive va fi ales un fir de executie cu o prioritate mai mica. In cazul n care toate

    firele au aceeasi prioritate ele sunt alese dupa un algoritm simplu de tip *round-ro&in*.

    De asemenea, planificarea este complet preemptiva : daca un fir cu prioritate mai mare dect firul care se

    executa la un moment dat solicita procesorul, atunci firul cu prioritate mai mare este imediat trecut n

    executie iar celalalt trecut n asteptare. lanificatorul /ava nu va ntrerupe nsa un fir de executie n

    favoarea altuia de aceeasi prioritate, nsa acest lucru l poate face sistemul de operare n cazul n care

    acesta aloca procesorul n cuante de timp 8un astfel de 52 este =indo!s >?0"9.

    Asadar, un fir de executie /ava cedeaza procesorul n una din situatiile :

    un fir de executie cu o prioritate mai mare solicita procesorul

    metoda sa runse termina vrea sa faca explicit acest lucru apelnd metoda #ield

    timpul alocat pentru executia sa a expirat 8pe 52 cu cuante de timp9

    In nici un caz corectitudinea unui program nu tre&uie sa se &azeze pe mecansimul de planificare a firelor

    de executie, deoarece acesta poate fi imprevizi&il si depinde de la un sistem de operare la altul.

    )n fir de executie de lunga durata si care nu cedeaza explicit procesorul la anumite intervale de timp astfel

    nct sa poata fi executate si celelalte fire de executie se numeste fir de executie egoist si tre&uie evitata

    scrierea lor, ntruct acapareaza pe termen nedefinit procesorul, &locnd efectiv executia celorlalte fire de

    executie pna la terminarea sa. )nele sistemele de operare com&at acest tip de comportament prin metodaalocarii procesorului n cuante de timp fiecarui fir de executie, nsa nu tre&uie sa ne &azam pe acest lucru

    la scrierea unui program. )n fir de executie tre&uie sa fie *corect* fata de celelalte fire si sa cedeze

    periodic procesorul astfel nct toate sa ai&a posi&ilitatea de a se executa.

    xemplu de fir de executie "e!oist"

    //un ir de executie care nu!ara pana la &''.''' din &''

  • 7/25/2019 Ciclul de Viata Al Unui Fir de Executie

    6/6

    s&.set9riorit# (Thread.7+89RI3RIT:);s> = new Selish(?irul >);s>.set9riorit# (Thread.7+89RI3RIT:);s&.start();s>.start();

    *

    *Firul de executie s1 are prioritate maxima si pna nu-si va termina executia nu-i va permite firului s$ sa

    execute nici o instructiune, acaparnd efectiv procesorul. %ezultatul va arata astfel:?irul & a auns la &''?irul & a auns la >''?irul & a auns la @''. . .?irul & a auns la AAA''?irul & a auns la &'''''?irul > a auns la &''?irul > a auns la >''. . .?irul > a auns la AAA''

    ?irul > a auns la &'''''%ezolvarea acestei pro&leme se face fie prin intermediul metodei statice #ielda clasei Threadcare

    determina firul de executie curent sa se opreasca temporar, dnd ocazia si altor fire sa se execute, fie prin

    *adormirea* temporara a firului curent cu ajutorul metodei sleep. +etoda runa clasei Selishar tre&ui

    rescrisa astfel:public oid run() %

    int i = ';while (i , &''''') %

    i --;i (i &'' == ')

    S#ste!.out.println(getNa!e()- a auns la -i);#ield(); //cede te!porar procesorul

    *rin metoda #ieldun fir de executie nu cedeaza procesorul dect firelor de executie care au aceeasi

    prioritate cu a sa si nu celor cu prioritati mai mici.