Sunteți pe pagina 1din 16

Clasa Graphics

Putei s v imaginai applet-ul drept o pnz pe care se vor desfura operaii grafice. Ai folosit deja metoda drawString () pentru a desena text ntr-un applet. Fontul i culoarea textului au fost alese anterior desenrii textului, n acelai fel n care un artist i alege culoarea i pensula nainte de a picta. Textul nu este singurul lucru pe care l putei desena n fereastra unui applet. Putei desena i linii, ovale, cercuri, arcuri, dreptunghiuri i alte poligoane. Majoritatea principalelor operaii de desenare sunt metode definite n clasa Graphics. ntr-un applet nu este nevoie s creai un obiect Graphics pentru a putea desena ceva aa cum poate v mai amintii, unul dintre argumentele metodei paint () este un obiect Graphics. Acest obiect reprezint fereastra applet-ului, iar metodele sale sunt folosite pentru a desena n applet. Clasa Graphics este parte a pachetului java.awt, deci toate applet-urile care deseneaz ceva trebuie s foloseasc instruciunea import pentru a putea folosi aceast clas.

Sistemul de coordonate grafice


Ca i metoda drawString(), toate celelalte metode grafice posed argumente care indic coordonatele x,y. Unele dintre acestea au mai multe seturi de coordonate, cum ar fi o linie, care posed un set de coordonate x,y ce indic punctul de nceput al liniei i nc un set de coordonate x,y care corespunde punctului final al liniei. Sistemul de coordonate Java folosete ca unitate de msur pixelul. Coordonatele punctului de origine 0,0 sunt situate n colul din stnga - sus al ferestrei Applet. Valoarea coordonatei x crete la dreapta originii 0,0, iar valoarea coordonatei y crete n jos. Acest lucru difer fa de alte sisteme de coordonate, n care originea 0,0 se afl n colul din stnga -jos i valoarea coordonatei y crete n sus. Toate valorile de pixeli sunt ntregi - nu se pot folosi valori zecimale pentru a afia ceva aflat ntre dou valori ntregi.

Desenarea i umplerea
Pentru majoritatea formelor pe care le desenai ntr-un applet sunt disponibile dou tipuri de metode: metode de desenare, care deseneaz conturul formei, i metode de umplere, care umplu forma cu culoarea curent. n fiecare tip de metod, conturul obiectului este, de asemenea, desenat cu culoarea curent.

Linii
Metoda drawLine este folosit pentru a desena o linie ntre dou puncte. Metoda primete patru argumente: coordonatele x,y ale punctului de nceput i coordonatele x, y ale punctului final. drawLine(x1, y1, x2, y2) ; Aceast metod deseneaz o linie ncepnd cu punctul de coordonate (x1, y1) i pn la punctul de coordonate (x2, y2). Grosimea liniei este de un pixel.

Dreptunghiuri
Clasa Graphics conine metode pentru dou tipuri de dreptunghiuri: dreptunghiuri normale i dreptunghiuri cu coluri . Ambele tipuri de dreptunghiuri pot fi desenate sub form de contur sau umplute cu culoarea curent. Pentru a desena un dreptunghi normal se folosete metoda drawRect() pentru contururi sau metoda fillRect() pentru forme umplute. Ambele metode preiau patru argumente: Coordonatele x i y ale colului din stnga - sus al dreptunghiului Limea dreptunghiului nlimea dreptunghiului drawRect(x,y,l,h)

Poligoane
Poligoanele pot fi desenate folosind metodele drawPolygon() i fillPolygon(). Pentru a desena un poligon avei nevoie de coordonatele x,y ale fiecrui punct care definete colurile poligonului. Poligoanele pot fi definite drept o serie de linii conectate una cu cealalt - se deseneaz o linie de la un punct iniial la un punct final, apoi punctul final este folosit ca punct iniial pentru o alt linie i aa mai departe. Putei specifica aceste coordonate n dou moduri: Ca o pereche de tablouri cu ntregi, dintre care unul pstreaz toate valorile coordonatei x i cellalt pstreaz toate valorile coordonatei y. Ca un obiect Polygon, creat folosind un tablou cu valori ntregi ale coordonatei x i un tablou cu valori ntregi ale coordonatei y. A doua metod este mai flexibil, deoarece permite adugarea individual a punctelor unui poligon, nainte de desenarea sa. n afar de coordonatele x i y, trebuie s specificai numrul de puncte al poligonului. Nu se pot specifica mai multe coordonate x,y dect numrul de puncte i nici invers. n oricare din aceste cazuri, compilatorul va semnala o eroare. Pentru a crea un obiect polygon, primul pas const n crearea unui poligon gol, printr-o instruciune new, ca n cazul urmtor: Polygon polig = new Polygon(); Mai putei crea un poligon pornind de la un set de puncte, folosind tablouri cu valori ntregi. Aceasta necesit un apel ctre constructorul Polygon (int [], int [], int), unde se specific tabloul cu valori pentru coordonata x, tabloul cu valori pentru coordonata y i numrul de puncte (coluri). Iat un exemplu de folosire a acestui constructor: int x[] = { 10, 20, 30, 40, 50 }; int y[] = { 15, 25, 35, 45, 55 }; int puncte = x.length; Polygon polig = new Polygon(x, y, puncte); Dup ce se creeaz obiectul Polygon, se pot aduga puncte folosind metoda addpoint(). Aceasta preia ca argumente coordonatele x, y i adaug punctul n poligon. lat un exemplu: polig.addPoint(60, 65);

Atunci cnd obiectul Polygon are toate punctele necesare, el poate fi desenat folosind una dintre metodele drawPolygon() sau fillPolygon() . Aceste metode au drept unic argument obiectul Polygon, ca n exemplul urmtor: ecran.drawPolygon(polig) ; Dac folosii metoda drawPolygon() n Java 1.02, putei nchide poligonul stabilind pentru ultimele coordonate x,y valori identice cu primele. Altfel, poligonul va rmne deschis pe una dintre laturi. Metoda fillPolygon() nchide automat forma poligonal, fr a mai fi nevoie de stabilirea coordonatelor finale.

Ovale
Metodele drawOval() i fillOval() sunt folosite pentru a desena cercuri i ovale (elipse). Metodele preiau patru argumente: coordonatele x, y ale ovalului limea i nlimea ovalului, care n cazul cercurilor iau valori egale Ovalele sunt tratate n acelai mod ca i colurile dreptunghiurilor rotunjite. Coordonata x,y va reprezenta colul din stnga - sus al zonei n care va fi desenat ovalul, aflndu-se de fapt la stnga i mai sus dect forma oval propriu-zis.

Arce
Un arc este o parte a unui oval, fiind implementat n Java ca o form eliptic parial desenat. Arcele sunt desenate folosind metodele drawArc() i fillArc(), care preiau ase argumente: coordonatele x, y ale ovalului din care face parte arcul; limea i nlimea ovalului; unghiul de unde se ncepe trasarea arcului; numrul de grade al arcului. Primele patru argumente sunt aceleai ca n cazul ovalului i se comport identic. Unghiul de nceput al arcului ia valori ntre 0 i 359 de grade i crete n sens trigonometric (invers acelor de ceasornic).

Copierea i tergerea
Clasa Graphics conine i cteva funcii de gen decupeaz-i-lipete (cut-and-paste), aplicabile ferestrei Applet: Metoda copyArea (), care copiaz o regiune dreptunghiular a ferestrei Applet ntr-o alt regiune a ferestrei. Metoda clearRect (), care decupeaz" o regiune dreptunghiular din fereastra Applet Metoda copyArea () preia ase argumente: Coordonatele x, y ale regiunii dreptunghiulare de copiat. Limea i nlimea regiunii. Distana pe orizontal i pe vertical, n pixeli, cu care se deplaseaz copia fa de regiunea iniial, nainte de afiare.

Urmtoarea instruciune copiaz o regiune de 100x100 pixeli ntr-o zon aflat cu 50 de pixeli mai la dreapta i cu 25 de pixeli mai jos: ecran.copyArea(0, 0, 100, 100, 50, 25); Metoda clearRect() preia aceleai patru argumente ca i metodele drawRect() sau fillRect(), umplnd regiunea dreptunghiular astfel definit cu culoarea curent de fundal a applet-ului. Dac dorii s tergei ntreaga fereastr Applet, putei determina mai nti dimensiunea ferestrei folosind metoda size(). Aceasta returneaz un obiect Dimension, care posed variabilele width (lime) i height (nlime); acestea reprezint dimensiunile applet-ului. lat un exemplu de folosire a acestei metode: ecran.clearRect(0, 0, size().width, size().height);

Text i fonturi
Obiectele clasei java.awt.Font sunt folosite pentru a putea utiliza metoda drawString() cu diferite fonturi. Obiectele Font conin numele, stilul i dimensiunea n puncte a unui font. O alt clas, FontMetrics, ofer metode pentru determinarea dimensiunilor i a caracterelor afiabile cu un anumit font, care pot fi folosite pentru lucruri cum ar fi formatarea i centrarea textului. Crearea obiectelor Font Un obiect Font este creat prin apelarea constructorului su cu trei argumente: Numele fontului Stilul fontului Dimensiunea n puncte a fontului Numele poate fi denumirea unui font specific, cum ar fi Arial sau Garamond Old Style, care va putea fi folosit dac este prezent (instalat) n sistemul pe care se ruleaz programul Java. Exist i alte nume care pot fi folosite pentru selectarea fonturilor interne, proprii Java: TimesRoman, Helvetica, Courier, Dialog i DialogInput. Pot fi selectate trei stiluri de fonturi, folosind constantele Font. PLAIN, Font. BOLD i Font. ITALIC. Aceste constante sunt ntregi i pot fi nsumate pentru a obine o combinaie de efecte. Ultimul argument al constructorului Font () este dimensiunea fontului. Urmtoarea instruciune creeaz un font Dialog de 24 de puncte, cu aldine cursive. Font f = new Font("Dialog", Font.BOLD + Font.ITALIC, 24); Desenarea caracterelor i a irurilor Pentru a seta fontul curent se folosete metoda setFont() a clasei Graphics, mpreun cu un obiect Font. Urmtoarea instruciune folosete un obiect Font denumit ft: ecran.setFont(ft); Textul poate fi afiat ntr-o fereastr Applet folosind metoda drawString(). Aceast metod folosete fontul curent selectat; dac nu a fost selectat nici un font, este folosit unul implicit. Poate fi selectat oricnd un nou font cu ajutorul metodei setFont (). Urmtoarea metod paint () creeaz un nou obiect Font, stabilete fontul curent la acest obiect, dup care afieaz irul Acesta este un font. la coordonatele 10,100. public void paint(Graphics ecran) { Font f = new Font("TimesRoman", Font.PLAIN, 72);

ecran.setFont(f); ecran.drawString(Acesta este un font.", 10, 100); } Ultimele dou argumente ale metodei drawString () sunt coordonatele x, y. Valoarea x reprezint locul de nceput al marginii din stnga a textului, iar y este valoarea la care se afieaz linia de baz a irului de text. Aflarea de informaii despre un font Clasa FontMetrics poate fi folosit pentru obinerea de informaii detaliate despre fontul curent, cum ar fi limea sau nlimea caracterelor pe care le poate afia. Pentru a folosi metodele clasei, trebuie mai nti creat un obiect FontMetrics prin metoda getFontMetrics (). Metoda primete un singur argument: un obiect Font. Tabelul prezint unele informaii pe care le putei obine despre dimensiunile fontului. Toate aceste metode pot fi apelate pentru un obiect FontMetrics. Tabelul Metode FontMetrics. Nume metod stringWidth (String) charWidth (char) getHeight () Aciune ntoarce limea total a irului, n pixeli ntoarce limea unui caracter dat ntoarce nlimea total a fontului

Culori
Clasele Color i ColorSpace din pachetul java.awt pot fi folosite pentru a aduce puin culoare n applet-urile i aplicaiile dumneavoastr. Cu ajutorul acestor clase putei stabili culorile curente folosite n operaiile de desenare, ca i culoarea de fundal pentru un applet sau alte ferestre. De asemenea, putei translata o culoare dintr-un sistem de descriere n altul. n mod prestabilit, Java folosete culorile conform unui sistem de descriere denumit sRGB. n acest sistem, o culoare este descris prin cantitatea de rou, verde i albastru pe care o conine de aici i iniialele R(ed), G(reen) i B(lue). Fiecare dintre aceste trei componente poate fi reprezentat ca un ntreg din gama 0-255. Negrul este 0, 0, 0 - lipsa complet a tuturor componentelor rou, verde, albastru. Albul este 255, 255, 255 - valoarea maxim a tuturor componentelor. Mai putei reprezenta valori sRGB folosind trei numere n virgul mobil, n domeniul dintre 0 i 1,0. Folosind sRGB, Java poate reprezenta milioane de culori aflate ntre cele dou extreme. Un sistem de descriere a culorilor mai este numit i palet sau spaiu de culori (color space), iar sRGB este doar unul dintre acestea. Exist i CMYK, un sistem folosit de imprimante i care descrie culorile prin procentul de Cyan (azuriu), Magenta (purpuriu), Yellow (galben) i Black (negru) pe care l conin. Java 2 suport folosirea oricrui spaiu de culori dorii, att timp ct folosii un obiect ColorSystem care definete respectivul sistem de descriere a culorilor. De asemenea, putei converti culorile din sRGB n alt spaiu de culori i invers. Reprezentarea intern a culorilor n Java folosind sRGB reprezint numai spaiul de culoare folosit n program. Dispozitivele de ieire, cum ar fi monitoarele sau imprimantele, pot avea i ele propriile spaii de culoare.

Atunci cnd afiai sau tiprii ceva cu o anumit culoare, dispozitivul de ieire s-ar putea s nu suporte culoarea respectiv. n acest caz, culoarea va fi nlocuit cu o alta sau cu o culoare impur (dithered), folosit pentru a aproxima culoarea care nu este disponibil. Acest lucru se ntmpl frecvent pe World Wide Web, cnd o culoare indisponibil este nlocuit cu una impur, care aproximeaz culoarea lips. Practic, culorile definite conform modelului sRGB nu vor putea fi reprezentate pe orice dispozitiv de ieire. Dac avei nevoie de un control mai precis al culorii, putei folosi ColorSpace sau alte clase din pachetul java.awt. color, introdus o dat cu Java 2. Pentru majoritatea programelor, folosirea sRGB, sistemul intern de reprezentare a culorilor, va fi suficient.

Folosirea obiectelor Color


Pentru a stabili culoarea curent pentru desenare, trebuie fie s creai un obiect Color care s reprezinte culoarea respectiv, fie s folosii una dintre culorile standard existente n clasa Color. Pentru a crea o culoare, exist dou metode de apelare a metodei constructor Color; Folosirea a trei ntregi care s reprezinte valorile sRGB pentru culoarea dorit Folosirea a trei numere n virgul mobil, care s reprezinte valorile sRGB pentru culoarea dorit Putei defini deci valoarea sRGB a culorii folosind fie trei variabile int, fie trei variabile float. lat un exemplu de instruciuni de acest gen: Color c1 = new Color(0.807F, 1F, OF); Color c2 = new Color(255, 204, 102); Obiectul c1 definete o culoare verde-neon, iar c2 o culoare maro-aurie

Testarea i stabilirea culorilor curente


Culoarea curent pentru desenare este desemnat folosind metoda setColor() a clasei Graphics. Aceast metod trebuie apelat pentru obiectul Graphics care reprezint zona n care desenai. ntr-un applet, acest obiect este cel transmis metodei paint (). O modalitate de a stabili culoarea de desenare este folosirea uneia dintre culorile standard, disponibile ca variabil de clas n clasa Color. Aceste culori folosesc urmtoarele variabile Color (avnd valorile sRGB indicate ntre paranteze): black (negru) (0,0,0) magenta (purpuriu)(255,0,255) blue (albastru) (0,0,255) orange (portocaliu)(255,200,0) cyan (azuriu)(0,255,255) pink (roz) (255.175,175) darkGray(gri nchis)(64,64,64) red (rosu) (255,0,0) gray (gri) (128,128,128) white (alb) (255,255,255) green (verde) (0,255,0) yellow (galben) (255,255,0) lightGray(gri deschis)(192,192,192) Urmtoarea instruciune stabilete culoarea curent pentru obiectul ecran folosind una dintre variabilele de clas standard: ecran.setColor(Color.pink) ; Dac ai creat un obiect Color, el poate fi setat ntr-un mod asemntor: Color pensula = new Color(255, 204, 102);

ecran.setColor(pensula) ; Dup ce ai stabilit culoarea curent, toate operaiile de desenare o vor folosi pe aceasta. Putei stabili culoarea de fundal (background) ntr-o fereastr Applet folosind metodele proprii applet-ului, setBackground() i setForeground(). Acestea sunt motenite de clasa Applet de la una dintre superclasele sale, aa nct toate applet-urile create vor moteni i ele aceste metode. Metoda setBackground() seteaz culoarea de fundal a ferestrei Applet. Ea primete ca singur argument un obiect color: setBackground(Color.white) ; Exist i o metod setForeground(), care este apelat pentru componentele interfeei utilizator, nu pentru obiectele Graphics. Funcioneaz la fel ca metoda setColor (), ns schimb culoarea unei componente a interfeei, cum ar fi un buton sau o fereastr. Deoarece un applet este o fereastr, putei folosi metoda setForeground() n metoda init() pentru a seta culorile pentru operaiile de desenare. Aceast culoare va fi folosit pn la alegerea unei alte culori cu una dintre metodele setForeground() sau setColor (). Dac dorii s aflai care este culoarea curent, putei folosi metoda getColor() pentru un obiect grafic, respectiv una dintre metodele getForeground() sau getBackground() pentru clasa Applet. Urmtoarea instruciune stabilete culoarea curent pentru ecran - un obiect Graphics - ca fiind aceeai cu fundalul applet-ului: ecran.setColor(getBackground());

Operaii grafice avansate folosind Java2D


Una dintre mbuntirile aduse n Java2 este Java2D, un set de clase pentru crearea unor imagini i texte bidirecionale de nalt calitate. Funciile Java2D conin: Modele speciale de umplere Linii de diferite grosimi Anti-aliasing pentru netezirea marginilor obiectelor desenate Conversia prin cast a unui obiect Graphics2D Operaiile de desenare nvate pn acum sunt apelate pentru obiecte Graphics. Pentru Java2D, acest obiect se utilizeaz pentru a crea un nou obiect Graphics2D public void paint(Graphics ecran) { Graphics2D ecran2D = (Graphics2D)ecran; }

Fire de execuie i sincronizare


O aplicaie Java ruleaz n interiorul unui proces al sistemului de operare. Acest proces const din segmente de cod i segmente de date mapate ntr-un spaiu virtual de adresare. Fiecare proces deine un numr de resurse alocate de ctre sistemul de operare, cum ar fi fiiere deschise, regiuni de memorie alocate dinamic, sau fire de execuie. Toate aceste resurse deinute de ctre un proces sunt eliberate la terminarea procesului de ctre sistemul de operare. Un fir de execuie este unitatea de execuie a unui proces. Fiecare fir de execuie are asociate o secven de instruciuni, un set de regitri CPU i o stiv. Atenie, un proces nu execut nici un fel de instruciuni. El este de fapt un spaiu de adresare comun pentru unul sau mai multe

fire de execuie. Execuia instruciunilor cade n responsabilitatea firelor de execuie. n cele ce urmeaz vom prescurta uneori denumirea firelor de execuie, numindu-le pur i simplu fire . n cazul aplicaiilor Java interpretate, procesul deine n principal codul interpretorului iar codul binar Java este tratat ca o zon de date de ctre interpretor. Dar, chiar i n aceast situaie, o aplicaie Java poate avea mai multe fire de execuie, create de ctre interpretor i care execut, seturi distincte de instruciuni binare Java. Fiecare dintre aceste fire de execuie poate rula n paralel pe un procesor separat dac maina pe care ruleaz aplicaia este o main cu mai multe procesoare. Pe mainile monoprocesor, senzaia de execuie n paralel a firelor de execuie este creat prin rotirea acestora pe rnd la controlul unitii centrale, cte o cuant de timp fiecare. Mediul de execuie Java execut propriul su control asupra firelor de execuie. Algoritmul pentru planificarea firelor de execuie, prioritile i strile n care se pot afla acestea sunt specifice aplicaiilor Java i implementate identic pe toate platformele pe care a fost portat mediul de execuie Java. Totui, acest mediu tie s profite de resursele sistemului pe care lucreaz. Dac sistemul gazd lucreaz cu mai multe procesoare, Java va folosi toate aceste procesoare pentru a-i planifica firele de execuie. n cazul mainilor multiprocesor, mediul de execuie Java i sistemul de operare sunt responsabile cu repartizarea firelor de execuie pe un procesor sau altul. Pentru programator, acest mecanism este complet transparent, neexistnd nici o diferen ntre scrierea unei aplicaii cu mai multe fire pentru o main cu un singur procesor sau cu mai multe. Desigur, exist ns diferene n cazul scrierii aplicaiilor pe mai multe fire de execuie fa de acelea cu un singur fir de execuie, diferene care provin n principal din cauza necesitii de sincronizare ntre firele de execuie aparinnd aceluiai proces. Sincronizarea firelor de execuie nseamn c acestea se ateapt unul pe cellalt pentru completarea anumitor operaii care nu se pot executa n paralel sau care trebuie executate ntr-o anumit ordine. Java ofer i n acest caz mecanismele sale proprii de sincronizare, extrem de uor de utilizat i nglobate n chiar sintaxa de baz a limbajului. La lansarea n execuie a unei aplicaii Java este creat automat i un prim fir de execuie, numit firul principal. Acesta poate ulterior s creeze alte fire de execuie care la rndul lor pot crea alte fire, i aa mai departe. Firele de execuie dintr-o aplicaie Java pot fi grupate n grupuri pentru a fi manipulate n comun. n afar de firele normale de execuie, Java ofer i fire de execuie cu prioritate mic care lucreaz n fundalul aplicaiei atunci cnd nici un alt fir de execuie nu poate fi rulat. Aceste fire de fundal se numesc demoni i execut operaii costisitoare n timp i independente de celelalte fire de execuie. De exemplu, n Java colectorul de gunoaie lucreaz pe un fir de execuie separat, cu proprieti de demon. n acelai fel poate fi gndit un fir de execuie care execut operaii de ncrcare a unor imagini din reea. O aplicaie Java se termin atunci cnd se termin toate firele de execuie din interiorul ei sau cnd nu mai exist dect fire demon. Terminarea firului principal de execuie nu duce la terminarea automat a aplicaiei. Crearea firelor de execuie Exist dou ci de definire de noi fire de execuie: derivarea din clasa Thread a noi clase i implementarea ntr-o clas a interfeei Runnable . n primul caz, noua clas motenete toate metodele i variabilele clasei Thread care implementeaz n mod standard, n Java, funcionalitatea de lucru cu fire de execuie. Singurul lucru pe care trebuie s-l fac noua clas este s reimplementeze metoda run care este apelat

automat de ctre mediul de execuie la lansarea unui nou fir. n plus, noua clas ar putea avea nevoie s implementeze un constructor care s permit atribuirea unei denumiri firului de execuie. Dac firul are un nume, acesta poate fi obinut cu metoda getName care returneaz un obiect de tip String . Iat un exemplu de definire a unui nou tip de fir de execuie:
class FirNou extends Thread { public FirNou( String nume ) { // apeleaz constructorul din Thread super( nume ); } public void run() { while( true ) { // fr sfrit System.out.println( getName() +" Tastati ^C" ); } } } Dac vom crea un nou obiect de tip FirNou

i l lansm n execuie acesta va afia la infinit mesajul "Tastai ^C". ntreruperea execuiei se poate face ntr-adevr prin tastarea caracterului ^C, caz n care ntreaga aplicaie este terminat. Atta timp ns ct noul obiect nu va fi ntrerupt din exterior, aplicaia va continua s se execute pentru c mai exist nc fire de execuie active i indiferent de faptul c firul de execuie principal s-a terminat sau nu. Iat i un exemplu de aplicaie care folosete aceast clas:
public class TestFirNou { public static void main( String[] arg) { new FirNou( "Primul" ).start(); } }

Metoda start, predefinit n obiectul Thread lanseaz execuia propriu-zis a firului. Desigur exist i ci de a opri execuia la nesfrit a firului creat fie prin apelul metodei stop , prezentat mai jos, fie prin rescrierea funciei run n aa fel nct execuia sa s se termine dup un interval finit de timp. A doua cale de definiie a unui fir de execuie este implementarea interfeei Runnable ntr-o anumit clas de obiecte. Aceast cale este cea care trebuie aleas atunci cnd clasa pe care o crem nu se poate deriva din clasa Thread pentru c este important s fie derivat din alt clas. Desigur, motenirea multipl ar rezolva aceast problem, dar Java nu are motenire multipl. Aceast nou cale se poate folosi n modul urmtor:
class Oclasa { } class FirNou extends Oclasa implements Runnable { public void run() { for( int i = 0; i < 100; i++ ) { System.out.println( "pasul " + i ); } }

} public class TestFirNou { public static void main( String argumente[ ] ) { new Thread( new FirNou() ).start(); // Obiectele sunt create i folosite imediat // La terminarea instruciunii, ele sunt automat // eliberate nefiind referite de nimic } } Dup se observ, clasa Thread are i un constructor care primete ca argument o instan a unei clase care implementeaz interfaa Runnable. n acest caz, la lansarea n execuie a noului fir, cu metoda start , se apeleaz metoda run din acest obiect i nu din instana a clasei Thread .

Atunci cnd dorim s crem un aplet care s ruleze pe un fir de execuie separat fa de pagina de navigator n care ruleaz pentru a putea executa operaii n fereastra apletului i n acelai timp s putem folosi n continuare navigatorul, suntem obligai s alegem cea de-a doua cale de implementare. Aceasta pentru c apletul nostru trebuie s fie derivat din clasa standard Applet . Singura alternativ care ne rmne este aceea de a implementa n aplet interfaa Runnable . Strile unui fir de execuie Un fir de execuie se poate afla n Java n mai multe stri, n funcie de ce se ntmpl cu el la un moment dat. Atunci cnd este creat, dar nainte de apelul metodei start, firul se gsete ntr-o stare pe care o vom numi Fir Nou Creat . n aceast stare, singurele metode care se pot apela pentru firul de execuie sunt metodele start i stop . Metoda start lanseaz firul n execuie prin apelul metodei run . Metoda stop omoar firul de execuie nc nainte de a fi lansat. Orice alt metod apelat n aceast stare provoac terminarea firului de execuie prin generarea unei excepii de tip IllegalThreadStateException . Dac apelm metoda start pentru un Fir Nou Creat firul de execuie va trece n starea Ruleaz. n aceast stare, instruciunile din corpul metodei run se execut una dup alta. Execuia poate fi oprit temporar prin apelul metodei sleep care primete ca argument un numr de milisecunde care reprezint intervalul de timp n care firul trebuie s fie oprit. Dup trecerea intervalului, firul de execuie va porni din nou. n timpul n care se scurge intervalul specificat de sleep, obiectul nu poate fi repornit prin metode obinuite. Singura cale de a iei din aceast stare este aceea de a apela metoda interrupt. Aceast metod genereaz o excepie de tip InterruptedException care nu este interceptat de sleep dar care trebuie interceptat obligatoriu de metoda care a apelat metoda sleep. De aceea, modul standard n care se apeleaz metoda sleep este urmtorul:
try { sleep( 1000 ); // o secund } catch( InterruptedException ) { }

Dac dorim oprirea firului de execuie pe timp nedefinit, putem apela metoda suspend. Aceasta trece firul de execuie ntr-o nou stare, numit Nu Ruleaz. Aceeai stare este folosit i pentru oprirea temporar cu sleep. n cazul apelului suspend ns, execuia nu va putea fi reluat dect printr-un apel al metodei resume. Dup acest apel, firul va intra din nou n starea Ruleaz .

Pe timpul n care firul de execuie se gsete n starea Nu Ruleaz , acesta nu este planificat niciodat la controlul unitii centrale, aceasta fiind cedat celorlalte fire de execuie din aplicaie. Firul de execuie poate intra n starea Nu Ruleaz i din alte motive. De exemplu se poate ntmpla ca firul s atepte pentru terminarea unei operaii de intrare/ieire de lung durat caz n care firul va intra din nou n starea Ruleaz doar dup terminarea operaiei. O alt cale de a ajunge n starea Nu Ruleaz este aceea de a apela o metod sau o secven de instruciuni sincronizat dup un obiect. n acest caz, dac obiectul este deja blocat, firul de execuie va fi oprit pn n clipa n care obiectul cu pricina apeleaz metoda notify sau notifyAll . Atunci cnd metoda run i-a terminat execuia, obiectul intr n starea Mort. Aceast stare este pstrat pn n clipa n care obiectul este eliminat din memorie de mecanismul de colectare a gunoaielor. O alt posibilitate de a intra n starea Mort este aceea de a apela metoda stop . Desigur, firul de execuie poate fi terminat i pe alte ci, caz n care metoda stop nu este apelat. n aceste situaii este preferabil s ne folosim de o clauz finally ca n exemplul urmtor:
try { firDeExecutie.start( ); } finally { ..// curenie }

n fine, dac nu se mai poate face nimic pentru c firul de execuie nu mai rspunde la comenzi, putei apela la calea disperat a metodei destroy. Din pcate, metoda destroy termin firul de execuie fr a proceda la curirile necesare n memorie. Atunci cnd un fir de execuie este oprit cu comanda stop, mai este nevoie de un timp pn cnd sistemul efectueaz toate operaiile necesare opririi. Din aceast cauz, este preferabil s ateptm n mod explicit terminarea firului prin apelul metodei join:
firDeExecutie.stop( ) try { firDeExecutie.join( ); } catch( InterruptedException e ) { }

Excepia de ntrerupere trebuie interceptat obligatoriu. Dac nu apelm metoda join pentru a atepta terminarea i metoda stop este de exemplu apelat pe ultima linie a funciei main , exist ansa ca sistemul s cread c firul auxiliar de execuie este nc n via i aplicaia Java s nu se mai termine rmnnd ntr-o stare de ateptare. O putei desigur termina tastnd ^C. Prioritatea firelor de execuie Fiecare fir de execuie are o prioritate cuprins ntre valorile MIN_PRIORITY i MAX_PRIORITY. Aceste dou variabile finale sunt declarate n clasa Thread. n mod normal ns, un fir de execuie are prioritatea NORM_PRIORITY, de asemenea definit n clasa Thread . Mediul de execuie Java planific firele de execuie la controlul unitii centrale n funcie de prioritatea lor. Dac exist mai multe fire cu prioritate maxim, acestea sunt planificate dup un algoritm numit round-robin. Firele de prioritate mai mic intr n calcul doar atunci cnd toate firele de prioritate mare sunt n starea Nu Ruleaz . Prioritatea unui fir de execuie se poate interoga cu metoda getPriority care ntoarce un numr ntreg care reprezint prioritatea curent a firului de execuie. Pentru a seta prioritatea, se folosete metoda setPriority care primete ca parametru un numr ntreg care reprezint prioritatea dorit.

Schimbarea prioritii unui fir de execuie este o treab periculoas dac metoda cu prioritate mare nu se termin foarte repede sau dac nu are opriri dese. n caz contrar, celelalte metode nu vor mai putea primi controlul unitii centrale. Exist ns situaii n care putem schimba aceast prioritate fr pericol, de exemplu cnd avem un fir de execuie care nu face altceva dect s citeasc caractere de la utilizator i s le memoreze ntr-o zon temporar. n acest caz, firul de execuie este n cea mai mare parte a timpului n starea Nu Ruleaz din cauz c ateapt terminarea unei operaii de intrare/ieire. n clipa n care utilizatorul tasteaz un caracter, firul va iei din starea de ateptare i va fi primul planificat la execuie din cauza prioritii sale ridicate. n acest fel utilizatorul are senzaia c aplicaia rspunde foarte repede la comenzile sale. n alte situaii, avem de executat o sarcin cu prioritate mic. n aceste cazuri, putem seta pentru firul de execuie care execut aceste sarcini o prioritate redus. Alternativ, putem defini firul respectiv de execuie ca un demon. Dezavantajul n aceast situaie este faptul c aplicaia va fi terminat atunci cnd exist doar demoni n lucru i exist posibilitatea pierderii de date. Pentru a declara un fir de execuie ca demon, putem apela metoda setDaemon. Aceast metod primete ca parametru o valoare boolean care dac este true firul este fcut demon i dac nu este adus napoi la starea normal. Putem testa faptul c un fir de execuie este demon sau nu cu metoda isDemon. Grupuri de fire de execuie Uneori avem nevoie s acionm asupra mai multor fire de execuie deodat, pentru a le suspenda, reporni sau modifica prioritatea n bloc. Din acest motiv, este util s putem grupa firele de execuie pe grupuri. Aceast funcionalitate este oferit n Java de ctre o clas numit ThreadGroup . La pornirea unei aplicaii Java, se creeaz automat un prim grup de fire de execuie, numit grupul principal, main. Firul principal de execuie face parte din acest grup. n continuare, ori de cte ori crem un nou fir de execuie, acesta va face parte din acelai grup de fire de execuie ca i firul de execuie din interiorul cruia a fost creat, n afar de cazurile n care n constructorul firului specificm explicit altceva. ntr-un grup de fire de execuie putem defini nu numai fire dar i alte grupuri de execuie. Se creeaz astfel o arborescen a crei rdcin este grupul principal de fire de execuie. Pentru a specifica pentru un fir un nou grup de fire de execuie, putem apela constructorii obinuii dar introducnd un prim parametru suplimentar de tip ThreadGroup . De exemplu, putem folosi urmtorul cod:
ThreadGroup tg = new ThreadGroup( "Noul grup" ); Thread t = new Thread( tg, "Firul de executie" );

Acest nou fir de execuie va face parte dintr-un alt grup de fire dect firul principal. Putem afla grupul de fire de execuie din care face parte un anumit fir apelnd metoda getThreadGroup , ca n secvena:
Thread t = new Thread( "Firul de Executie" ); ThreadGroup tg = t.getThreadGroup();

Operaiile definite pentru un grup de fire de execuie sunt clasificabile n operaii care acioneaz la nivelul grupului, cum ar fi aflarea numelui, setarea unei prioriti maxime, etc., i operaii care acioneaz asupra fiecrui fir de execuie din grup, cum ar fi stop, suspend sau resume. Enumerarea firelor de execuie Pentru a enumera firele de execuie active la un moment dat, putem folosi metoda enumerate definit n clasa Thread precum i n clasa ThreadGroup . Aceast metod primete ca parametru o

referin ctre un tablou de referine la obiecte de tip Thread pe care l umple cu referine ctre fiecare fir activ n grupul specificat. Pentru a afla cte fire active sunt n grupul respectiv la un moment dat, putem apela metoda activeCount din clasa ThreadGroup . De exemplu:
ThreadGroup grup = Thread.currentThread().getThreadGroup(); int numarFire = grup.activeCount(); Thread fire[] = new Thread[numarFire]; grup.enumerate( fire ); for( int i = 0; i < numar; i++ ) { System.out.println( fire[i].toString() );

Metoda enumerate ntoarce numrul de fire memorate n tablou, care este identic cu numrul de fire active. Sincronizare n unele situaii se poate ntmpla ca mai multe fire de execuie s vrea s acceseze aceeai variabil. n astfel de situaii, se pot produce ncurcturi dac n timpul unuia dintre accese un alt fir de execuie modific valoarea variabilei. Limbajul Java ofer n mod nativ suport pentru protejarea acestor variabile. Suportul este construit de fapt cu granulaie mai mare dect o singur variabil, protecia fcndu-se la nivelul obiectelor. Putem defini metode, n cadrul claselor, care sunt sincronizate. Pe o instan de clas, la un moment dat, poate lucra o singur metod sincronizat. Dac un alt fir de execuie ncearc s apeleze aceeai metod pe aceeai instan sau o alt metod a clasei de asemenea declarat sincronizat, acest al doilea apel va trebui s atepte nainte de execuie eliberarea instanei de ctre cealalt metod. n afar de sincronizarea metodelor, se pot sincroniza i doar blocuri de instruciuni. Aceste sincronizri se fac tot n legtur cu o anumit instan a unei clase. Aceste blocuri de instruciuni sincronizate se pot executa doar cnd instana este liber. Se poate ntmpla ca cele dou tipuri de sincronizri s se amestece, n sensul c obiectul poate fi blocat de un bloc de instruciuni i toate metodele sincronizate s atepte, sau invers. Declararea unui bloc de instruciuni sincronizate se face prin: synchronize ( Instan ) { Instruciuni } iar declararea unei metode sincronizate se face prin folosirea modificatorului synchronize la implementarea metodei. Un exemplu Exemplul urmtor implementeaz soluia urmtoarei probleme: ntr-o ar foarte ndeprtat triau trei nelepi filozofi. Aceti trei nelepi i pierdeau o mare parte din energie certndu-se ntre ei pentru a afla care este cel mai nelept. Pentru a trana problema o dat pentru totdeauna, cei trei nelepi au pornit la drum ctre un al patrulea nelept pe care cu toii l recunoteau c ar fi mai bun dect ei. Cnd au ajuns la acesta, cei trei i-au cerut s le spun care dintre ei este cel mai nelept. Acesta, a scos cinci plrii, trei negre i dou albe, i li le-a artat explicndu-le c i va lega la ochi i le va pune n cap cte o plrie, cele dou rmase ascunzndu-le. Dup aceea, le va dezlega ochii, i fiecare dintre ei va vedea culoarea plriei celorlali dar nu i-o va putea vedea pe a sa. Cel care i va da primul seama ce culoare are propria plrie, acela va fi cel mai nelept.

Dup explicaie, neleptul i-a legat la ochi, le-a pus la fiecare cte o plrie neagr i le-a ascuns pe celelalte dou. Problema este aceea de a descoperi care a fost raionamentul celui care a ghicit primul c plria lui este neagr. Programul urmtor rezolv problema dat n felul urmtor: Fiecare nelept privete plriile celorlali doi. Dac ambele sunt albe, problema este rezolvat, a lui nu poate fi dect neagr. Dac vede o plrie alb i una neagr, atunci el va trebui s atepte puin s vad ce spune cel cu plria neagr. Dac acesta nu gsete soluia, nseamn c el nu vede dou plrii albe, altfel ar fi gsit imediat rspunsul. Dup un scurt timp de ateptare, neleptul poate s fie sigur c plria lui este neagr. n fine, dac ambele plrii pe care le vede sunt negre, va trebui s atepte un timp ceva mai lung pentru a vedea dac unul dintre concurenii si nu ghicete plria. Dac dup scurgerea timpului nici unul nu spune nimic, nseamn c nici unul nu vede o plrie alb i una neagr. nseamn c propria plrie este neagr. Desigur, raionamentul pleac de la ideea c ne putem baza pe faptul c toi nelepii gndesc i pot rezolva probleme uoare. Cel care ctig a gndit doar un pic mai repede. Putem simula viteza de gndire cu un interval aleator de ateptare pn la luarea deciziilor. n realitate, intervalul nu este aleator ci dictat de viteza de gndire a fiecrui nelept. Cei trei nelepi sunt implementai identic sub form de fire de execuie. Nu ctig la fiecare rulare acelai din cauza caracterului aleator al implementrii. neleptul cel mare este firul de execuie principal care controleaz activitatea celorlalte fire i le servete cu date, culoarea plriilor, doar n msura n care aceste date trebuie s fie accesibile. Adic nu se poate cere propria culoare de plrie. Culoarea iniial a plriilor se poate rescrie din linia de comand.
import java.awt.Color; // clasa Filozof implementeaza comportamentul unui concurent class Filozof extends Thread { // parerea concurentului despre culoarea palariei sale. // Null daca nca nu si-a format o parere. Color parere = null; Filozof( String nume ) { super( nume ); } public void run() { // concurentii firului curent Filozof concurenti[] = new Filozof[2]; // temporar Thread fire[] = new Thread[10]; int numarFire = enumerate( fire ); for( int i = 0, j = 0; i < numarFire && j < 2; i++ ) { if( fire[i] instanceof Filozof && fire[i] != this ) { concurenti[j++] = (Filozof)fire[i]; } } while( true ) { Color primaCuloare = Concurs.culoare( this, concurenti[0] ); Color adouaCuloare = Concurs.culoare( this, concurenti[1] ); if( primaCuloare == Color.white && adouaCuloare == Color.white ) { synchronized( this ) { parere = Color.black; } } else if( primaCuloare == Color.white ){

try{ sleep( (int)( Math.random()*500) ); } catch( InterruptedException e ){ }; if( Concurs.culoare( this, concurenti[1]) != concurenti[1].aGhicit()) { synchronized( this ) { parere = Color.black; }; } } else if( adouaCuloare == Color.white ) { try{ sleep( (int)( Math.random()*500)); } catch( InterruptedException e ) { }; if( Concurs.culoare(this, concurenti[0] ) != concurenti[0].aGhicit()) { synchronized( this ) { parere = Color.black; }; } } else { try { sleep( (int)( Math.random()*500)+500 ); } catch( InterruptedException e ) { }; if( Concurs.culoare(this, concurenti[0]) != concurenti[0].aGhicit() && Concurs.culoare( this, concurenti[1] ) !=concurenti[1].aGhicit() ) { synchronized( this ) { parere = Color.black; }; } } } } public synchronized Color aGhicit() { return parere; } }

import java.awt.Color; public class Concurs { private static Color palarii[] = { Color.black, Color.black, Color.white }; private static Filozof filozofi[] = new Filozof[3]; public static void main( String args[] ) { for( int i = 0; i < args.length && i < 3; i++ ) { if( args[i].equalsIgnoreCase( "alb" ) ) { palarii[i] = Color.white; } else if(args[i].equalsIgnoreCase("negru")) { palarii[i] = Color.black; } }

for( int i = 0; i < 3; i++ ) { filozofi[i] = new Filozof( "Filozoful " + ( i + 1 ) ); } for( int i = 0; i < 3; i++ ) { filozofi[i].start(); } System.out.println( "Concurenti:" ); for( int i = 0; i < 3; i++ ) { System.out.println( "\t" +filozofi[i].getName() + " "+ (( palarii[i] == Color.white ) ?"alb":"negru" ) ); } boolean gata=false; while( !gata) { for( int i = 0; i < 3; i++ ) { if( filozofi[i].aGhicit()==palarii[i] ) { System.out.println( filozofi[i].getName() +" a ghicit." ); gata=true; } } } for( int i = 0; i < 3; i++ ) { filozofi[i].stop(); try { filozofi[i].join(); } catch( InterruptedException e ) {}; } } public static Color culoare( Filozof filozof, Filozof concurent ) { if( filozof != concurent ) { for( int i = 0; i < 3; i++ ) { if( filozofi[i] == concurent ) { return palarii[i]; } } } return null; } }

S-ar putea să vă placă și

  • Curs 11
    Curs 11
    Document7 pagini
    Curs 11
    Marian Pf
    Încă nu există evaluări
  • Programa Licenta Colegiu Info 2006
    Programa Licenta Colegiu Info 2006
    Document2 pagini
    Programa Licenta Colegiu Info 2006
    Marian Pf
    Încă nu există evaluări
  • Curs 10
    Curs 10
    Document10 pagini
    Curs 10
    Marian Pf
    Încă nu există evaluări
  • Curs 9
    Curs 9
    Document16 pagini
    Curs 9
    Marian Pf
    Încă nu există evaluări
  • Curs 8
    Curs 8
    Document18 pagini
    Curs 8
    Marian Pf
    Încă nu există evaluări
  • Curs 7
    Curs 7
    Document17 pagini
    Curs 7
    Marian Pf
    Încă nu există evaluări
  • Curs 6
    Curs 6
    Document18 pagini
    Curs 6
    Marian Pf
    Încă nu există evaluări
  • Curs 2
    Curs 2
    Document16 pagini
    Curs 2
    Marian Pf
    Încă nu există evaluări
  • Curs 1
    Curs 1
    Document16 pagini
    Curs 1
    smeche_hd
    Încă nu există evaluări
  • Curs 4
    Curs 4
    Document13 pagini
    Curs 4
    Marian Pf
    Încă nu există evaluări
  • Curs 3
    Curs 3
    Document17 pagini
    Curs 3
    Marian Pf
    Încă nu există evaluări