Document, comentariu, eseu, bacalaureat, liceu si facultate
Top documenteAdmitereTesteUtileContact
      
    


 


Ultimele referate adaugate

Adauga referat - poti sa ne ajuti cu un referat?

Politica de confidentialitate



Ultimele referate descarcare de pe site
  CREDITUL IPOTECAR PENTRU INVESTITII IMOBILIARE (economie)
  Comertul cu amanuntul (economie)
  IDENTIFICAREA CRIMINALISTICA (drept)
  Mecanismul motor, Biela, organe mobile proiect (diverse)
  O scrisoare pierduta (romana)
  O scrisoare pierduta (romana)
  Ion DRUTA (romana)
  COMPORTAMENT PROSOCIAL-COMPORTAMENT ANTISOCIAL (psihologie)
  COMPORTAMENT PROSOCIAL-COMPORTAMENT ANTISOCIAL (psihologie)
  Starea civila (geografie)
 

Ultimele referate cautate in site
   domnisoara hus
   legume
    istoria unui galban
   metanol
   recapitulare
   profitul
   caract
   comentariu liric
   radiolocatia
   praslea cel voinic si merele da aur
 
despre:
 
Fire de executie si sincronizare JAVA
Colt dreapta
Vizite: ? Nota: ? Ce reprezinta? Intrebari si raspunsuri
 

 

O aplicatie Java ruleaza in interiorul unui proces al sistemului de operare. Acest proces consta din segmente de cod si segmente de date mapate intr-un spatiu virtual de adresare. Fiecare proces detine un numar de resurse alocate de catre sistemul de operare, cum ar fi fisiere deschise, regiuni de memorie alocate dinamic, sau fire de executie. Toate aceste resurse detinute de catre un proces sunt eliberate la terminarea procesului de catre sistemul de operare.

Un fir de executie este unitatea de executie a unui proces. Fiecare fir de executie are asociate o secventa de instructiuni, un set de regisitri CPU si o stiva. Atentie, un proces nu executa nici un fel de instructiuni. El este de fapt un spatiu de adresare comun pentru unul sau mai multe fire de executie. Executia instructiunilor cade in responsabilitatea firelor de executie. In cele ce urmeaza vom prescurta uneori denumirea firelor de executie, numindu-le pur si simplu fire .

In cazul aplicatiilor Java interpretate, procesul detine in principal codul interpretorului iar codul binar Java este tratat ca o zona de date de catre interpretor. Dar, chiar si in aceasta situatie, o aplicatie Java poate avea mai multe fire de executie, create de catre interpretor si care executa, seturi




distincte de instructiuni binare Java.

Fiecare dintre aceste fire de executie poate rula in paralel pe un procesor separat daca masina pe care ruleaza aplicatia este o masina cu mai multe procesoare. Pe masinile monoprocesor, senzatia de executie in paralel a firelor de executie este creata prin rotirea acestora pe rand la controlul unitatii centrale, cate o cuanta de timp fiecare. Algoritmul de rotire al firelor de executie este de tip round-robin.

Mediul de executie Java executa propriul sau control asupra firelor de executie. Algoritmul pentru planificarea firelor de executie, prioritatile si starile in care se pot afla acestea sunt specifice aplicatiilor Java si implementate identic pe toate platformele pe care a fost portat mediul de executie Java. Totusi, acest mediu stie sa profite de resursele sistemului pe care lucreaza. Daca sistemul gazda lucreaza cu mai multe procesoare, Java va folosi toate aceste procesoare pentru a-si planifica firele de executie. Daca sistemul ofera multitasking preemptiv, multitaskingul Java va fi de asemenea preemptiv, etc.

In cazul masinilor multiprocesor, mediul de executie Java si sistemul de operare sunt responsabile cu repartizarea firelor de executie pe un procesor sau altul. Pentru programator, acest mecanism este complet transparent, neexistand nici o diferenta intre scrierea unei aplicatii cu mai multe fire pentru o masina cu un singur procesor sau cu mai multe. Desigur, exista insa diferente in cazul scrierii aplicatiilor pe mai multe fire de executie fata de acelea cu un singur fir de executie, diferente care provin in principal din cauza necesitatii de sincronizare intre firele de executie apartinand aceluiasi proces.

Sincronizarea firelor de executie inseamna ca acestea se asteapta unul pe celalalt pentru completarea anumitor operatii care nu se pot executa in paralel sau care trebuie executate intr-o anumita ordine. Java ofera si in acest caz mecanismele sale proprii de sincronizare, extrem de usor de utilizat si inglobate in chiar sintaxa de baza a limbajului.

La lansarea in executie a unei aplicatii Java este creat automat si un prim fir de executie, numit firul principal. Acesta poate ulterior sa creeze alte fire de executie care la randul lor pot crea alte fire, si asa mai departe. Firele de executie dintr-o aplicatie Java pot fi grupate in grupuri pentru a fi manipulate in comun.

In afara de firele normale de executie, Java ofera si fire de executie cu prioritate mica care lucreaza in fundalul aplicatiei atunci cand nici un alt fir de executie nu poate fi rulat. Aceste fire de fundal se numesc demoni si executa operatii costisitoare in timp si independente de celelalte fire de executie. De exemplu, in Java colectorul de gunoaie lucreaza pe un fir de executie separat, cu proprietati de demon. In acelasi fel poate fi gandit un fir de executie care executa operatii de incarcare a unor imagini din retea.

O aplicatie Java se termina atunci cand se termina toate firele de executie din interiorul ei sau cand nu mai exista decat fire demon. Terminarea firului principal de executie nu duce la terminarea automata a aplicatiei. ^

9.1 Crearea firelor de executie

Exista doua cai de definire de noi fire de executie: derivarea din clasa Thread a noi clase si implementarea intr-o clasa a interfetei Runnable .

In primul caz, noua clasa mosteneste toate metodele si variabilele clasei Thread care implementeaza in mod standard, in Java, functionalitatea de lucru cu fire de executie. Singurul lucru pe care trebuie sa-l faca noua clasa este sa reimplementeze metoda run care este apelata automat de catre mediul de executie la lansarea unui nou fir. In plus, noua clasa ar putea avea nevoie sa implementeze un constructor care sa permita atribuirea unei denumiri firului de executie.

Daca firul are un nume, acesta poate fi obtinut cu metoda getName care returneaza un obiect de tip String .

Iata un exemplu de definire a unui nou tip de fir de executie:

class FirNou extends Thread A
public FirNou( String nume ) A
// apeleaza constructorul din Thread
super( nume ); 
S
public void run() A
while( true ) A // fara sfarsit
System.out.println( getName() +
" Tastati ^C" );
S
S
S

Daca vom crea un nou obiect de tip FirNou si il lansam in executie acesta va afisa la infinit mesajul "Tastati ^C". Intreruperea executiei se poate face intr-adevar prin tastarea caracterului ^C, caz in care intreaga aplicatie este terminata. Atata timp insa cat noul obiect nu va fi intrerupt din exterior, aplicatia va continua sa se execute pentru ca mai exista inca fire de executie active si indiferent de faptul ca firul de executie principal s-a terminat sau nu.

Iata si un exemplu de aplicatie care foloseste aceasta clasa:

public TestFirNou A
public static void main( Stringai ) A
new FirNou( "Primul" ).start();
S
S

Metoda start , predefinita in obiectul Thread lanseaza executia propriu-zisa a firului. Desigur exista si cai de a opri executia la nesfarsit a firului creat fie prin apelul metodei stop , prezentata mai jos, fie prin rescrierea functiei run in asa fel incat executia sa sa se termine dupa un interval finit de timp.

A doua cale de definitie a unui fir de executie este implementarea interfetei Runnable intr-o anumita clasa de obiecte. Aceasta cale este cea care trebuie aleasa atunci cand clasa pe care o cream nu se poate deriva din clasa Thread pentru ca este important sa fie derivata din alta clasa. Desigur, mostenirea multipla ar rezolva aceasta problema, dar Java nu are mostenire multipla.

Aceasta noua cale se poate folosi in modul urmator:

class Oclasa A
.
S
class FirNou extends Oclasa implements Runnable A
public void run() A
for( int i = 0; i < 100; i++ ) A
System.out.println( "pasul " + i );
S
S
.
S
public class TestFirNou A
public static void main( String argumenteai ) A
new Thread( new FirNou() ).start();
// Obiectele sunt create si folosite imediat
// La terminarea instructiunii, ele sunt automat
// eliberate nefiind referite de nimic
S
S

Dupa cum observati, clasa Thread are si un constructor care primeste ca argument o instanta a unei clase care implementeaza interfata Runnable . In acest caz, la lansarea in executie a noului fir, cu metoda start , se apeleaza metoda run din acest obiect si nu din instanta a clasei Thread .

Atunci cand dorim sa cream un aplet care sa ruleze pe un fir de executie separat fata de pagina de navigator in care ruleaza pentru a putea executa operatii in fereastra apletului si in acelasi timp sa putem folosi in continuare navigatorul, suntem obligati sa alegem cea de-a doua cale de implementare. Aceasta pentru ca apletul nostru trebuie sa fie derivat din clasa standard Applet . Singura alternativa care ne ramane este aceea de a implementa in aplet interfata Runnable . ^

9.2 Starile unui fir de executie

Un fir de executie se poate afla in Java in mai multe stari, in functie de ce se intampla cu el la un moment dat.

Atunci cand este creat, dar inainte de apelul metodei start, firul se gaseste intr-o stare pe care o vom numi Fir Nou Creat . In aceasta stare, singurele metode care se pot apela pentru firul de executie sunt metodele start si stop . Metoda start lanseaza firul in executie prin apelul metodei run . Metoda stop omoara firul de executie inca inainte de a fi lansat. Orice alta metoda apelata in aceasta stare provoaca terminarea firului de executie prin generarea unei exceptii de tip IllegalThreadStateException .

Daca apelam metoda start pentru un Fir Nou Creat firul de executie va trece in starea Ruleaza . In aceasta stare, instructiunile din corpul metodei run se executa una dupa alta. Executia poate fi oprita temporar prin apelul metodei sleep care primeste ca argument un numar de milisecunde care reprezinta intervalul de timp in care firul trebuie sa fie oprit. Dupa trecerea intervalului, firul de executie va porni din nou.

In timpul in care se scurge intervalul specificat de sleep , obiectul nu poate fi repornit prin metode obisnuite. Singura cale de a iesi din aceasta stare este aceea de a apela metoda interrupt . Aceasta metoda arunca o exceptie de tip InterruptedException care nu este prinsa de sleep dar care trebuie prinsa obligatoriu de metoda care a apelat metoda sleep . De aceea, modul standard in care se apeleaza metoda sleep este urmatorul:

.
try A
sleep( 1000 ); // o secunda
S catch( InterruptedException ) A
.
S
.

Daca dorim oprirea firului de executie pe timp nedefinit, putem apela metoda suspend . Aceasta trece firul de executie intr-o noua stare, numita Nu Ruleaza . Aceeasi stare este folosita si pentru oprirea temporara cu sleep . In cazul apelului suspend insa, executia nu va putea fi reluata decat printr-un apel al metodei resume . Dupa acest apel, firul va intra din nou in starea Ruleaza .

Pe timpul in care firul de executie se gaseste in starea Nu Ruleaza , acesta nu este planificat niciodata la controlul unitatii centrale, aceasta fiind cedata celorlalte fire de executie din aplicatie.

Firul de executie poate intra in starea Nu Ruleaza si din alte motive. De exemplu se poate intampla ca firul sa astepte pentru terminarea unei operatii de intrare/iesire de lunga durata caz in care firul va intra din nou in starea Ruleaza doar dupa terminarea operatiei.

O alta cale de a ajunge in starea Nu Ruleaza este aceea de a apela o metoda sau o secventa de instructiuni sincronizata dupa un obiect. In acest caz, daca obiectul este deja blocat, firul de executie va fi oprit pana in clipa in care obiectul cu pricina apeleaza metoda notify sau notifyAll .

In fine, atunci cand metoda run si-a terminat executia, obiectul intra in starea Mort . Aceasta stare este pastrata pana in clipa in care obiectul

este eliminat din memorie de mecanismul de colectare a gunoaielor. O alta posibilitate de a intra in starea Mort este aceea de a apela metoda stop .

Atunci cand se apeleaza metoda stop , aceasta arunca cu o instructiune throw o eroare numita ThreadDeath . Aceasta poate fi prinsa de catre cod pentru a efectua curatenia necesara. Codul necesar este urmatorul:

.
try A
firDeExecutie.start();
.
S catch( ThreadDeath td ) A
. // curatenie
throw td; // se arunca obiectul mai departe
// pentru a servi la distrugerea
// firului de executie
S

Desigur, firul de executie poate fi terminat si pe alte cai, caz in care metoda stop nu este apelata si eroarea ThreadDeath nu este aruncata. In aceste situatii este preferabil sa ne folosim de o clauza finally ca in:

.
try A
firDeExecutie.start();
.
S finally A
..// curatenie
S

In fine, daca nu se mai poate face nimic pentru ca firul de executie nu mai raspunde la comenzi, puteti apela la calea disperata a metodei destroy . Din pacate, metoda destroy termina firul de executie fara a proceda la curatirile necesare in memorie.

Atunci cand un fir de executie este oprit cu comanda stop , mai este nevoie de un timp pana cand sistemul efectueaza toate operatiile necesare opririi. Din aceasta cauza, este preferabil sa asteptam in mod explicit terminarea firului prin apelul metodei join :

firDeExecutie.stop()
try A
firDeExecutie.join();
S catch( InterruptedException e ) A
.
S

Exceptia de intrerupere trebuie prinsa obligatoriu. Daca nu apelam metoda join pentru a astepta terminarea si metoda stop este de exemplu apelata pe ultima linie a functiei main , exista sansa ca sistemul sa creada ca firul auxiliar de executie este inca in viata si aplicatia Java sa nu se mai termine ramanand intr-o stare de asteptare. O puteti desigur termina tastand ^C. ^

9.3 Prioritatea firelor de executie

Fiecare fir de executie are o prioritate cuprinsa intre valorile MIN_PRIORITY si MAX_PRIORITY. Aceste doua variabile finale sunt declarate in clasa Thread . In mod normal insa, un fir de executie are prioritatea NORM_PRIORITY, de asemenea definita in clasa Thread .

Mediul de executie Java planifica firele de executie la controlul unitatii centrale in functie de prioritatea lor. Daca exista mai multe fire cu prioritate maxima, acestea sunt planificate dupa un algoritm round-robin. Firele de prioritate mai mica intra in calcul doar atunci cand toate firele de prioritate mare sunt in starea Nu Ruleaza .

Prioritatea unui fir de executie se poate interoga cu metoda getPriority care intoarce un numar intreg care reprezinta prioritatea curenta a firului de executie. Pentru a seta prioritatea, se foloseste metoda setPriority care primeste ca parametru un numar intreg care reprezinta prioritatea dorita.

Schimbarea prioritatii unui fir de executie este o treaba periculoasa daca metoda cu prioritate mare nu se termina foarte repede sau daca nu are opriri dese. In caz contrar, celelalte metode nu vor mai putea primi controlul unitatii centrale.

Exista insa situatii in care putem schimba aceasta prioritate fara pericol, de exemplu cand avem un fir de executie care nu face altceva decat sa citeasca caractere de la utilizator si sa le memoreze intr-o zona temporara. In acest caz, firul de executie este in cea mai mare parte a timpului in starea Nu Ruleaza din cauza ca asteapta terminarea unei operatii de intrare/iesire. In clipa in c

are utilizatorul tasteaza un caracter, firul va iesi din starea de asteptare si va fi primul planificat la executie din cauza prioritatii sale ridicate. In acest fel utilizatorul are senzatia ca aplicatia raspunde foarte repede la comenzile sale.

In alte situatii, avem de executat o sarcina cu prioritate mica. In aceste cazuri, putem seta pentru firul de executie care executa aceste sarcini o prioritate redusa.

Alternativ, putem defini firul respectiv de executie ca un demon. Dezavantajul in aceasta situatie este faptul ca aplicatia va fi terminata atunci cand exista doar demoni in lucru si exista posibilitatea pierderii de date. Pentru a declara un fir de executie ca demon, putem apela metoda setDaemon. Aceasta metoda primeste ca parametru o valoare booleana care daca este true firul este facut demon si daca nu este adus inapoi la starea normala. Putem testa faptul ca un fir de executie este demon sau nu cu metoda isDemon^

9.4 Grupuri de fire de executie

Uneori avem nevoie sa actionam asupra mai multor fire de executie deodata, pentru a le suspenda, reporni sau modifica prioritatea in bloc. Din acest motiv, este util sa putem grupa firele de executie pe grupuri. Aceasta functionalitate este oferita in Java de catre o clasa numita ThreadGroup .

La pornirea unei aplicatii Java, se creeaza automat un prim grup de fire de executie, numit grupul principal, main . Firul principal de executie

face parte din acest grup. In continuare, ori de cate ori cream un nou fir de executie, acesta va face parte din acelasi grup de fire de executie ca si firul de executie din interiorul caruia a fost creat, in afara de cazurile in care in constructorul firului specificam explicit altceva.

Intr-un grup de fire de executie putem defini nu numai fire dar si alte grupuri de executie. Se creeaza astfel o arborescenta a carei radacina este grupul principal de fire de executie.

Pentru a specifica pentru un fir un nou grup de fire de executie, putem apela constructorii obisnuiti dar introducand un prim parametru suplimentar de tip ThreadGroup . De exemplu, putem folosi urmatorul cod:

ThreadGroup tg = new ThreadGroup( "Noul grup" );
Thread t = new Thread( tg, "Firul de executie" );

Acest nou fir de executie va face parte dintr-un alt grup de fire decat firul principal. Putem afla grupul de fire de executie din care face parte un anumit fir apeland metoda getThreadGroup , ca in secventa:

Thread t = new Thread( "Firul de Executie" );
ThreadGroup tg = t.getThreadGroup();

Operatiile definite pentru un grup de fire de executie sunt clasificabile in operatii care actioneaza la nivelul grupului, cum ar fi aflarea numelui, setarea unei prioritati maxime, etc., si operatii care actioneaza asupra fiecarui fir de executie din grup, cum ar fi stop , suspend sau resume . Unele dintre aceste operatii necesita aprobarea controloarelor de securitate acest lucru facandu-se printr-o metoda numita checkAccess . De exemplu, nu puteti seta prioritatea unui fir de executie decat daca aveti drepturile de acces necesare. ^

9.5 Enumerarea firelor de executie

Pentru a enumera firele de executie active la un moment dat, putem folosi metoda enumerate definita in clasa Thread precum si in clasa ThreadGroup . Aceasta metoda primeste ca parametru o referinta catre un tablou de referinte la obiecte de tip Thread pe care il umple cu referinte catre fiecare fir activ in grupul specificat.

Pentru a afla cate fire active sunt in grupul respectiv la un moment dat, putem apela metoda activeCount din clasa ThreadGroup . De exemplu:

public listeazaFire A
ThreadGroup grup = Thread.currentThread().getThreadGroup();
int numarFire = grup.activeCount();
Thread fireai = new ThreadanumarFirei;
grup.enumerate( fire );
for( int i = 0; i < numar; i++ ) A
System.out.println( fireaii.toString() );
S
S

Metoda enumerate intoarce numarul de fire memorate in tablou, care este identic cu numarul de fire active. ^

9.6 Sincronizare

In unele situatii se poate intampla ca mai multe fire de executie sa vrea sa acceseze aceeasi variabila. In astfel de situatii, se pot produce incurcaturi daca in timpul unuia dintre accese un alt fir de executie modifica valoarea variabilei.

Limbajul Java ofera in mod nativ suport pentru protejarea acestor variabile. Suportul este construit de fapt cu granulatie mai mare decat o singura variabila, protectia facandu-se la nivelul obiectelor. Putem defini metode, in cadrul claselor, care sunt sincronizate.

Pe o instanta de clasa, la un moment dat, poate lucra o singura metoda sincronizata. Daca un alt fir de executie incearca sa apeleze aceeasi metoda pe aceeasi instanta sau o alta metoda a clasei de asemenea declarata sincronizata, acest al doilea apel va trebui sa astepte inainte de executie eliberarea instantei de catre cealalta metoda.

In afara de sincronizarea metodelor, se pot sincroniza si doar blocuri de instructiuni. Aceste sincronizari se fac tot in legatura cu o anumita instanta a unei clase. Aceste blocuri de instructiuni sincronizate se pot executa doar cand instanta este libera. Se poate intampla ca cele doua tipuri de sincronizari sa se amestece, in sensul ca obiectul poate fi blocat de un bloc de instructiuni si toate metodele sincronizate sa astepte, sau invers.

Declararea unui bloc de instructiuni sincronizate se face prin:

synchronize ( Instanta ) A

Instructiuni

S

iar declararea unei metode sincronizate se face prin folosirea modificatorului synchronize la implementarea metodei. ^

9.7 Un exemplu

Exemplul urmator implementeaza solutia urmatoarei probleme: Intr-o tara foarte indepartata traiau trei intelepti filozofi. Acesti trei intelepti isi pierdeau o mare parte din energie certandu-se intre ei pentru a afla care este cel mai intelept. Pentru a transa problema o data pentru totdeauna, cei trei intelepti au pornit la drum catre un al patrulea intelept pe care cu totii il recunosteau ca ar fi mai bun decat ei.

Cand au ajuns la acesta, cei trei i-au cerut sa le spuna care dintre ei este cel mai intelept. Acesta, a scos cinci palarii, trei negre si doua albe, si li le-a aratat explicandu-le ca ii va lega la ochi si le va pune in cap cate o palarie, cele doua ramase ascunzandu-le. Dupa aceea, le va dezlega ochii, si fiecare dintre ei va vedea culoarea palariei celorlalti dar nu si-o va putea vedea pe a sa. Cel care isi va da primul seama ce culoare are propria palarie, acela va fi cel mai intelept.

Dupa explicatie, inteleptul i-a legat la ochi, le-a pus la fiecare cate o palarie neagra si le-a ascuns pe celelalte doua. Problema este aceea de a descoperi care a fost rationamentul celui care a ghicit primul ca palaria lui este neagra.

Programul urmator rezolva problema data in felul urmator: Fiecare intelept priveste palariile celorlalti doi. Daca ambele sunt albe, problema este rezolvata, a lui nu poate fi decat neagra. Daca vede o palarie alba si una neagra, atunci el va trebui sa astepte putin sa vada ce spune cel cu palaria neagra. Daca acesta nu gaseste solutia, inseamna ca el nu vede doua palarii albe, altfel ar fi gasit imediat raspunsul. Dupa un scurt timp de asteptare, inteleptul poate sa fie sigur ca palaria lui este neagra.

In fine, daca ambele palarii pe care le vede sunt negre, va trebui sa astepte un timp ceva mai lung pentru a vedea daca unul dintre concurentii sai nu ghiceste palaria. Daca dupa scurgerea timpului nici unul nu spune nimic, inseamna ca nici unul nu vede o palarie alba si una neagra. Inseamna ca propria palarie este neagra.

Desigur, rationamentul pleaca de la ideea ca ne putem baza pe faptul ca toti inteleptii gandesc si pot rezolva probleme usoare. Cel care castiga a gandit doar un pic mai repede. Putem simula viteza de gandiri cu un interval aleator de asteptare pana la luarea deciziilor. In realitate, intervalul nu este aleator ci dictat de viteza de gandire a fiecarui intelept.

Cei trei intelepti sunt implementati identic sub forma de fire de executie. Nu castiga la fiecare rulare acelasi din cauza caracterului aleator al implementarii. Inteleptul cel mare este firul de executie principal care controleaza activitatea celorlalte fire si le serveste cu date, culoarea palariilor, doar in masura in care aceste date trebuie sa fie accesibile. Adica nu se poate cere propria culoare de palarie.

Culoarea initiala a palariilor se poate rescrie din linia de comanda.

import java.awt.Color;
// clasa Filozof implementeaza comportamentul
// unui concurent
class Filozof extends Thread A
// parerea concurentului despre culoarea
// palariei sale. Null daca inca nu si-a
// format o parere.
Color parere = null;
Filozof( String nume ) A
super( nume );
S
public void run() A
// concurentii firului curent
Filozof concurentiai = new Filozofa2i;
// temporar
Thread fireai = new Threada10i;
int numarFire = enumerate( fire );
for( int i = 0, j = 0; i < numarFire &&   j < 2; i++ ) A
if( fireaii instanceof Filozof && 
fireaii != this ) A
concurentiaj++i = (Filozof)fireaii;
S
S
while( true ) A
Color primaCuloare = Concurs.culoare( this, 
concurentia0i );
Color adouaCuloare =
 Concurs.culoare( this, concurentia1i );
if( primaCuloare == Color.white &&
adouaCuloare == Color.white ) A
synchronized( this ) A
parere = Color.black;
S
S else if( primaCuloare == Color.white )A
tryA
sleep( 500 );
S catch( InterruptedException e )A
S;
if( Concurs.culoare( this, concurentia1i) != concurentia1i.aGhicit()) A
synchronized( this ) A
parere = Color.black;
S;
S
S else if( adouaCuloare == Color.white ) A
tryA
 sleep( (int)( Math.random()*500));
S catch( InterruptedException e ) A
S;
if( Concurs.culoare(this, concurentia0i ) != concurentia0i.aGhicit()) A
synchronized( this ) A
parere = Color.black;
S;
S
S else A
try A
sleep( (int)( Math.random()*500)+500 );
 S catch( InterruptedException e ) A
S;
if( Concurs.culoare(this, concurentia0i) != concurentia0i.aGhicit() &&
 Concurs.culoare( this, 
concurentia1i ) !=
concurentia1i.aGhicit() ) A
synchronized( this ) A
parere = Color.black;
S;
S
S
S
S
public synchronized Color aGhicit() A
return parere;
S
S
public class Concurs A
private static Color palariiai = A
Color.black, Color.black, Color.black
 S;
private static Filozof filozofiai = new Filozofa3i;
public static void main( String argsai ) A
for( int i = 0; i < args.length && i <   3; i++ ) A
if( argsaii.equalsIgnoreCase( "alb" ) ) A
palariiaii = Color.white;
S else if(argsaii.equalsIgnoreCase("negru")) A
palariiaii = Color.black;
S
S
for( int i = 0; i < 3; i++ ) A
filozofiaii = new Filozof( "Filozoful " + 
( i + 1 ) );
S
for( int i = 0; i < 3; i++ ) A
filozofiaii.start();
S
System.out.println( "Concurenti:" );
for( int i = 0; i < 3; i++ ) A
System.out.println( "\t" +
filozofiaii.getName() + " "
+ (( palariiaii == Color.white ) ?
"alb":"negru" ) );
S
gata:
while( true ) A
for( int i = 0; i < 3; i++ ) A
if( filozofiaii.aGhicit()==palariiaii ) A
System.out.println( 
filozofiaii.getName() +
" a ghicit." );
break gata;
S
S
S
for( int i = 0; i < 3; i++ ) A
filozofiaii.stop();
try A
filozofiaii.join();
S catch( InterruptedException e ) AS;
S
S
public static Color culoare( Filozof filozof,
Filozof concurent ) A
if( filozof != concurent ) A
for( int i = 0; i < 3; i++ ) A
if( filozofiaii == concurent ) A
return palariiaii;
S
S
S
return null;
S
S ^

9.8 Un exemplu Runnable

Exemplul urmator implementeaza problema celor 8 dame, si anume: gaseste toate posibilitatile de a aseza pe o tabla de sah 8 regine in asa fel incat acestea sa nu se bata intre ele. Reginele se bat pe linie, coloana sau in diagonala.

Solutia de fata extinde problema la o tabla de NxN casute si la N regine. Parametrul N este citit din tagul HTML asociat apletului.

import java.awt.*;
import java.applet.Applet;
public
class QueensRunner extends Applet implements Runnable A
 int n;
 int regineai;
 int linie;
 Image queenImage;
 Thread myThread;
 public void start() A
if( myThread == null ) A
myThread = new Thread( this, "Queens" );
myThread.start();
S
 S
 public void stop() A
myThread.stop();
myThread = null;
 S
 public void run() A
while( myThread != null ) A
 nextSolution();
 repaint();
 try A
 myThread.sleep( 1000 );
 S catch ( InterruptedException e )A
 S
 S
 S
 boolean isGood() A
 for( int i = 0; i < linie; i++ ) A
 if( reginealiniei == regineaii ||
 Math.abs( regineaii - 
reginealiniei ) == Math.abs( i - linie ) ) A
 return false;
 S
 S
 return true;
 S
 
 void nextSolution() A
 while( true ) A
 if( linie < 0 ) A
 linie = 0;
 S
 reginealiniei++;
 if( reginealiniei > n ) A
 reginealiniei = 0;
 linie--;
 S else A
 if( isGood() ) A
 linie++;
 if( linie >= n ) A
 break;
 S
 S
 S
 S 
 S
 
 public void init() A
 String param = getParameter( "Dimension" );
 if( param == null ) A
 n = 4;
 S else A
 try A
 n = Integer.parseInt( param );
 S catch( NumberFormatException e ) A
 n = 4;
 S
 if( n < 4 ) A
 n = 4;
 S
 S
 regine = new intan + 1i;
 for( int i = 0; i < n; i++ ) A
 regineaii = 0;
 S
 linie = 0;
 queenImage = getImage(getCodeBase(), "queen.gif"   );
 S
 public void paint( Graphics g ) A
 Dimension d = size();
 g.setColor( Color.red );
 int xoff = d.width / n;
 int yoff = d.height / n;
 for( int i = 1; i < n; i++ ) A
 g.drawLine( xoff * i, 0, xoff * i, d.height );
 g.drawLine( 0, yoff * i, d.width, yoff * i );
 S
 for( int i = 0; i < n; i++ ) A
 for( int j = 0; j < n; j++ ) A
 if( regineaii - 1 == j ) A
 g.drawImage(queenImage, 
i*xoff + 1, j*yoff + 1, this);
 S
 S
 S
 S
 public String getAppletInfo() A
 return "Queens by E. Rotariu";
 S
S ^

Colt dreapta
Creeaza cont
Comentarii:

Nu ai gasit ce cautai? Crezi ca ceva ne lipseste? Lasa-ti comentariul si incercam sa te ajutam.
Esti satisfacut de calitarea acestui document, eseu, cometariu? Apreciem aprecierile voastre.

Nume (obligatoriu):

Email (obligatoriu, nu va fi publicat):

Site URL (optional):


Comentariile tale: (NO HTML)


Noteaza documentul:
In prezent fisierul este notat cu: ? (media unui numar de ? de note primite).

2345678910

 
Copyright© 2005 - 2024 | Trimite document | Harta site | Adauga in favorite
Colt dreapta