Sunteți pe pagina 1din 87

INTRODUCERE

Java
TM
este un limbaj de programare de nivel nalt,
dezvoltat de JavaSoft, companie n cadrul firmei Sun
Microsystems. Caracteristicile principale ale limbajului sunt:
simplitate, obinut! prin eliminarea supranc!rc!rii operatorilor,
mo"tenirii multiple, robustee, obinut! prin eliminarea pointerilor
pentru programator, administrarea automat! a memoriei, complet
orientat pe obiecte. #"urina n ceea ce priveste programarea n
reea mbinat! cu securitate ridicat!, neutraliatatea din punct de
vedere ar$itectural precum "i portabililtatea, independent! de
platforma de lucru, aceea"i aplicaie rul%nd, far! nici o modificare,
pe sisteme diferite cum ar fi &indo's, #()*, +inu, sau
Macintos$, lucru care aduce economii substaniale firmelor care
dezvolt! aplicaii pentru )nternet, deoarece programele Java pot fi
at%t interpretate, c%t "i compilate. Codul de octei obinut la
compilare este interpretat de mediul Java "i de aceea poate fi rulat
pe orice platform! care folose"te mediul de e,ecuie J-M .
ma"ina virtual! Java. +imbajul Java
TM
este creat iniial dup! C "i
C//, de aceea trecerea de la C, C// la Java
TM
se face relativ u"or.
+imbajul Java
TM
permite programarea cu fire de execuie
0multit$eaded1 mult mai clar "i mai sigur, at%t pentru aplicaii pe un
singur calculator, c%t "i pentru cele din )nternet, )ntranet sau reele
de telefonie mobi!. +imbajul Java
TM
pare s! fie cea mai reu"it!
alegere, n caliate de platform! pentru studierea program!rii
concurente.
+ucarea dat! este adresat! studenilor cu specializarea
Calculatoare de la 2acultatea C)M. 2iecare din cele patru p!ri ale
lucr!rii conine material teoretic cu e,emple de programe. +a
sf%r"itul fiec!rei p!ri se propune c%te o lucrare de laborator. 3entru
a fi admis la lucrarea de laborator studentul trebuie s! r!spund!
corect la ntreb!rile teoretice, puse de profesor, la tema dat!.
+ucrarea de laborator se va considera susinut! n cazul c%nd
4
studentul prezint! rularea corect! a programului "i raportul. 5area
de seam! pentru fiecare lucrare de laborator include: foaia de titlu,
tema, scopul lucr!rii, coninutul problemei propuse spre rezolvare,
descrierea noiunilor teoretice utilizate pentru rezolvarea
problemei, listingul programului, rezultatele obinute n urma
lans!rii programului pe calculator, bibliografia utilizat!. 6aportul
trebuie sa fie prezentat la control n form! electronic fi"ier de tip
7.doc sau 7.java cu documentarea respectiv! a lucr!rii, "i tip!rit pe
foi n formatul 89.
Spre rezolvare se propun cate zece variante de probleme
la fiecare lucrare de laborator. 2iecare student "i va alege c%te o
problem! conform variantei din tabel:
(r Std
(r.+ab
1 2 3 4 5 6 7 8 9 10
+ab. : : ; < = 9 > ? @ :A 4
+ab. = :A = 4 : ? < 9 ; > @
+ab. 4 < @ 9 ? > :A = 4 ; :
+ab. 9 4 9 @ > < ? ; : = :A
unde pe orizontal! se indic! num!rul de ordine al studentului din
registru n subgrup!. 5e e,emplu, studentul cu nr. > va efectua la
lucr!rile de laborator problemele 9, ?, > "i < respectiv.
9
PARTEA 1
1.1 Fire de execuie
1.1.1 Ce e!"e u# $ir de execuie %
2irele de e,ecuie fac trecerea de la programarea
secvenial! la programarea concurent! #n program secvenial
reprezint! modelul clasic de program: are un nceput, o secven! de
e,ecuie a instruciunilor sale "i un sf%r"it. Cu alte cuvinte, la un
moment dat programul are un singur punct de e,ecuie. #n
program aflat n e,ecuie se numeste proces. #n sistem de operare
monotasBing 0MSC5DS1 nu este capabil sa e,ecute dec%t un singur
proces la un moment dat, n timp ce un sistem de operare
multitasBing 0#()*, &indo's1 poate rula oric%te procese n
acela"i timp 0concurent1, aloc%nd periodic cuante din timpul de
lucru al C3# fiec!rui proces. 8m reamintit acest lucru deoarece
noiunea de fir de e,ecuie nu are sens dec%t n cadrul unui sistem
de operare multitasBing. #n fir de e,ecuie este similar unui proces
secvenial n sensul c! are un nceput, o secven! de e,ecuie "i un
sf%r"it. 5iferena ntre un fir de e,ecuie "i un proces const! n
faptul c! un fir de e,ecuie nu poate rula independent, ci trebuie s!
ruleze n cadrul unui proces.


>
a1 b1
2ig.: 2ire de e,ecuie n cadrul
unui program
3rogram cu un fir de e,ecuieE
3rogram cu mai multe fire de e,ecuie
Fn fig. : se indic! locul firelor de e,ecuie n cadrul programului.
Definiie
#n fir de execuie este o succesiune secvenial! de
instruciuni care se e,ecut! n cadrul unui proces.
#n program "i poate defini ns! nu doar un fir de e,ecuie, ci
oric%te, ceea ce nseamn! c! n cadrul unui proces se pot e,ecuta
simultan mai multe fire de e,ecuie, permi%nd e,ecuia concurent!
a sarcinilor independente ale acelui program. #n fir de e,ecuie
poate fi asem!nat cu o versiune redus! a unui proces, ambele
rul%nd simultan "i independent pe o structur! secvenial! de
e,ecuie a instruciunilor sale. 5e asemenea e,ecuia simultan! a
firelor de e,ecuie n cadrul unui proces este similar! cu e,ecuia
concurent! a proceselor: sistemul de operare va aloca ciclic cuante
din timpul procesorului fiec!rui fir de e,ecuie p%n! la terminarea
lor. 5in acest motiv firele de e,ecuie mai sunt numite "i procese
uoare. Care ar fi ns! deosebirile ntre un fir de e,ecuie "i un
procesG Fn primul r%nd, deosebirea major! const! n faptul c! firele
de e,ecuie nu pot rula dec%t n cadrul unui proces. D alt! deosebire
rezult! din faptul c! fiecare proces are propria sa memorie 0propriul
s!u spaiu de adrese1, iar la crearea unui nou proces 0forB1 este
realizat! o copie e,act! a procesului p!rinte : cod / dateE la crearea
unui fir de e,ecuie nu este copiat dec%t codul procesului p!rinteE
toate firele de e,ecuie au deci acces la acelea"i date, datele
procesului original. 8stfel, un fir de e,ecuie mai poate fi privit "i
ca un context de execuie n cadrul unui proces p!rinte. 2irele de
e,ecuie sunt utile n multe privine, ns! uzual ele sunt folosite
pentru e,ecutarea unor operaii consumatoare de timp f!r! a bloca
procesul principal: calcule matematice, asteptarea eliber!rii unei
resurse, acestea realiz%nduCse de obicei n fundal.
<
1.1.2 C&#cure#' "(re'd)uri*&r
2!r! a intra ntrCo discuie pe teme $ard'are, este bine de
spus c! procesoarele calculatoarelor pot e,ecuta doar o instruciune
la un moment dat. 5e ce spunem c! t$readCuri diferite se e,ecut! n
acela"i timpG Spun%nd simultan, nu nseamn! numai lucruri n
medii diferite. 3e o ma"in! multiprocesor, t$readCurile pot e,ista pe
procesoare diferite n acela"i timp fizic, aceasta menin%nduCse
valabil c$iar dac! procesoarele sunt pe calculatoare diferite
conectate ntrCo reea. 5ar "i pe o ma"in! cu un singur procesor,
t$readCurile pot mp!ri acela"i procesor, rul%nd ntrCo manier!
ntreesut!, competiia pentru timpii C3# cre%nd iluzia c! ele se
e,ecut! simultan. 8ceast! iluzie pare real! c%nd 4A de imagini
distincte pe secund! captate de oc$iul uman sunt percepute ntrCun
flu, continuu de imagine. Comutarea ntre t$readCuri are "i ea un
pre: consum! timp C3# pentru ca acesta s! ng$ee starea unui
t$read "i s! dezg$ee starea unui alt t$read 0sc$imbare de conte,t1.
5ac! t$readCurile concurente sunt e,ecutate pe acela"i procesor "i
toate e,ecut! calcule, atunci timpul total de e,ecuie nu va lua mai
mult dec%t timpul de e,ecuie al unui program secvenial care
realizeaz! acela"i lucru. 5in moment ce ntrCun sistem
monoprocesor t$readCurile concur! la timpul procesor cum este
posibil! cre"terea vitezei sistemuluiG 8ceasta se realizeaz! prin
ntreesarea diferitelor faze ale diferitelor t$readCuri. Multe tasBCuri
pot fi segmentate logic n tipuri de faze: faza de calcul "i faza )HD.
2aza de calcul necesit! atenia ma,ima din partea C3#C
ului prin utilizarea diferitelor metode de calcul. 2aza de )HD
0intrareHie"ire1 necesit! atenie ma,im! din partea perifericelor
0imprimante, $ard discuri, pl!ci de reea, etc1 "i n aceste situaii
procesorul este n general liber, a"tept%nd ca perifericul s!C"i
termine sarcina. Cre"terea vitezei este obinut! prin ntreesarea
fazelor. Fn timp ce un t$read se afl! ntrCo faz! de )HD a"tept%nd ca o
secven! de date s! fie nc!rcat! de pe $ard disB, un t$read cu o
?
faz! de calcul poate ocupa procesorul "i c%nd ajunge la o faz! )HD,
cel!lalt t$read 0care tocmai a terminat faza )HD proprie1 poate
ncepe s! utilizeze C3#Cul.
1.1.3 Cre're' u#ui $ir de execuie
Ca orice alt obiect n Java, un fir de e,ecuie este o
instan! a unei clase. 2irele de e,ecuie definite de o clas! vor avea
acela"i cod, prin urmare, "i aceea"i secven! de instruciuni.
Crearea unei clase care s! defineasc! fire de e,cuie poate fi f!cut!
prin dou! modalit!i:
1. +ri# ex"i#dere' c*'!ei T(re'd
2. +ri# i,+*e,e#"'re' i#"er$eei Ru##'-*e
Drice clas! ale c!rei instane vor fi e,ecutate ntrCun fir de e,ecuie
trebuie declarat! ca fiind Runnable. 8ceasta este o interfa! care
conine o singur! metod!, "i anume metoda run. 8sadar, orice clas!
ce descrie fire de e,ecuie va conine o metod! run() n care este
implementat codul ce va fi e,ecutat de firul de e,ecuie. )nterfaa
Runnable este conceput! ca fiind un protocol comun pentru
obiectele care doresc s! e,ecute un cod pe durata e,istenei lor
0care reprezint! fire de e,ecuie1. Cea mai important! clas! care
implementeaz! interfaa Runnable este clasa Thread. Clasa Thread
implementeaz! un fir de e,ecuie generic care, implicit, nu face
nimic. Cu alte cuvinte, metoda run nu conine nici un cod. Drice fir
de e,ecuie este o instan! a clasei Thread sau a unei subclase a sa.
1.1.3.1 Ex"i#dere' c*'!ei T(re'd
Cea mai simpl! metod! de a crea un fir de e,ecuie, care
s! realizeze ceva, este e,tinderea clasei Thread "i supradefinirea
metodei run a acesteia. 2ormatul general al unei astfel de clase
este:
@
public class SimpleThread extends Thread {
public SimpleThread(String nume) {
super(nume);
//apelez constructorul superclasei Thread
}
public void run() {
//codul executat de firul de execuie
}
}
3rima metod! a clasei este constructorul, care prime"te ca argument
un "ir ce va reprezenta numele firului de e,ecuie creat n
momentul c%nd constructorul este apelat.
SimpleThread t ! ne" SimpleThread(#$ava#);
//creeaza un fir de execuie cu numele $ava
Fn cazul n care nu vrem s! dam nume firelor de e,ecuie pe care le
cre!m, atunci putem renuna la definirea acestui constructor "i s!
r!m%nem doar cu constructorul implicit, f!r! argumente, care
creeaz! un fir de e,ecuie f!r! nici un nume. #lterior acesta poate
primi un nume cu metoda set%ame(String).
Ivident, se pot defini "i ali constructori, ace"tia fiind utili
c%nd vrem s! trimitem diver"i parametri firului de e,ecuie.
8 doua metod! este metoda run, JinimaJ oric!rui fir de e,ecuie n
care scriem efectiv codul pe care trebuie s!Cl e,ecute firul de
e,ecuie. #n fir de e,ecuie creat nu este automat pornit, lansarea
sa n e,ecuie se realizeaz! prin metoda start, definit! de
asemenea n clasa Thread.
SimpleThread t ! ne" SimpleThread(#$ava#);
t&start();
//creeaz' (i lanseaz' un fir de execuie
S! consider!m n continuare un e,emplu n care definim un fir de
e,ecuie ce afi"eaz! numerele ntregi dintrCun interval cu un anumit
pas. 2irul de e,ecuie este implementat de clasa )ounter.
class )ounter extends Thread {
//clasa care define(te firul de execuie
private int from* to* step;
;
public )ounter(int from* int to* int step) {
this&from ! from;
this&to ! to;
this&step ! step;
}
public void run() {
for(int i ! from; i +! to; i ,! step)
S-stem&out&print(i , # # );
}
}
public class Test)ounter { //clasa principal'
public static void main(String args./) {
)ounter cnt0* cnt1;
cnt0 ! ne" )ounter(2* 02* 1);
//numar' de la 2 la 022 cu pasul 3
cnt1 ! ne" )ounter(022* 122* 02);
//numar' de la 022 la 122 cu pasul 02
cnt0&start();
cnt1&start();
//pornim firele de execuie
//ele vor fi distruse automat la terminarea lor
}
}
K%ndind secvenial, sCar crede c! acest program va afi"a prima data
numerele de la A la :AA cu pasul >, apoi numerele de la :AA la =AA
cu pasul :A, ntruc%t primul apel este c!tre contorul cnt:, deci
rezultatul afi"at pe ecran ar trebui s! fie: A > :A :> =A => 4A 4> 9A
9> >A >> <A <> ?A ?> @A @> ;A ;> :AA :AA ::A :=A :4A :9A :>A
:<A :?A :@A :;A =AA.
Fn realitate ns!, rezultatul obinut va fi o intercalare de valori
produse de cele dou! fire de e,ecuie ce ruleaz! simultan. +a rul!ri
diferite se pot obine rezultate diferite deoarece timpul alocat
:A
fiec!rui fir de e,ecuie poate s! nu fie acela"i, el fiind controlat de
procesor ntrCo manier! JaparentJ aleatoare: 2 022 3 002 02 012
03 042 12 052 13 150 160 170 180 190 200 42 43 52 53
32 33 62 63 72 73 82 83 92 93 022:
1.1.3.2 I,+*e,e#"'re' i#"er$eei Runnable
Ce facem ns! c%nd dorim s! cre!m o clas! care
instaniaz! fire de e,ecuie, iar aceasta are deja o superclas!, "tiind
c! n Java nu este permis! mo"tenirea multipl!G
class ;ir<xecuie extends ='rinte* Thread //ilegal >
Fn acest caz nu mai putem e,tinde clasa Thread* ci trebuie s!
implement!m direct n clasa noastr! interfaa Runnable. Clasa
Thread implementeaza ea ns!"i interfaa Runnable "i, din acest
motiv, la e,tinderea ei obinem o implementare implicit! a
interfeei. 8sadar, interfaa Runnable permite unei clase s! fie
active, f!r! a e,tinde clasa Thread.
)nterfaa Runnable se g!se"te n pac$etul ?ava&lang "i este
definit! astfel:
public interface Runnable {
pulic abstract void run( );
}
3rin urmare, o clas! care instaniaz! fire de e,ecuie prin
implementarea interfeei Runnable trebuie obligatoriu s!
implementeze metoda run. 2ormatul general al unei clase care
implementeaz! interfaa Runnable este:
public class SimpleThread implements Runnable {
private Thread simpleThread ! null;
public SimpleThread() {
if (simpleThread !! null) {
simpleThread ! ne" Thread(this);
simpleThread&start();
}
public void run() {
::
//codul executat de firul de execuie
}
}
Spre deosebire de modalitatea anterioar!, se pierde ns! tot suportul
oferit de clasa Thread pentu crearea unui fir de e,ecuie. Simpla
instaniere a unei clase care implementeaz! interfaa Runnable nu
creeaz! nici un fir de e,ecuie. 5in acest motiv crearea firelor de
e,ecuie prin instanierea unei astfel de clase trebuie f!cut! e,plicit.
Cum se realizeaz! acest lucruG Fn primul r%nd, trebuie declarat un
obiect de tip Thread ca variabil! membr! a clasei respective. 8cest
obiect va reprezenta firul de e,ecuie propriuCzis al c!rui cod se
g!se"te n clasa noastr!:
private Thread simpleThread ! null;
#rm!torul pas este instanierea "i iniializarea firului de e,ecuie.
8cest lucru se realizeaz! ca pentru orice alt obiect prin
instruciunea ne", urmat! de un apel la un constructor al clasei
Thread, ns! nu la oricare dintre ace"tia. Trebuie apelat
constructorul care s! primeasc! drept argument o instan! a clasei
noastre. 5up! creare, firul de e,ecuie poate fi lansat printrCun apel
la metoda start. 08ceste operaiuni sunt scrise de obicei n
constructorul clasei noastre pentru a fi e,ecutate la iniializarea
unei instane, dar pot fi scrise oriunde n corpul clasei sau c$iar n
afara ei1
simpleThread ! ne" Thread( this );
simpleThread&start();
Specificarea argumentului this n constructorul clasei Thread
determin! crearea unui fir de e,ecuie care la lansarea sa va c!uta
n clasa noastr! metoda run "i o va e,ecuta. 8cest constructor
accept! ca argument orice instan! a unei clase J6unnableJ. 8sadar,
metoda run nu trebuie apelat! e,plicit, acest lucru realiz%nduCse
automat la apelul metodei start().
8pelul e,plicit al metodei run nu va furniza nici o eroare, ns!
aceasta va fi e,ecutat! ca orice alt! metod!, deci nu ntrCun fir de
e,ecuie. Sa rescriem acum e,emplul anterior 0afi"area numerelor
:=
ntregi dintrCun interval cu un anumit pas1, folosind interfaa
Runnable. -om vedea c! implementarea interfeei Runnable
permite o fle,ibilitate sporit! n lucrul cu fire de e,ecuie.
.'ri'#"' 1 /!"'#d'rd0
Crearea firului de e,ecuie se realizeaz! n constructorul clasei
)ounter@
class )ounter implements Runnable {
private Thread counterThread ! null;
private int from* to* step;
public )ounter(int from* int to* int step) {
this&from ! from;
this&to ! to;
this&step ! step;
if (counterThread !! null) {
counterThread ! ne" Thread(this);
counterThread&start();
}
}
public void run() {
for(int i ! from; i +! to; i ,! step)
S-stem&out&print(i , # # );
}
}
public class TestThread1 {
public static void main(String args./) {
)ounter cnt0* cnt1;
//lansez primul fir de execuie (prin constructor)
cnt0 ! ne" )ounter(2* 022* 3);
//lansez al doilea fir de execuie (prin constructor)
cnt1 ! ne" )ounter(022* 122* 02);
}
}
.'ri'#"' 2
Crearea firului de e,ecuie se realizeaz! n afara clasei )ounter:
class )ounter implements Runnable {
private int from* to* step;
:4
public )ounter(int from* int to* int step) {
this&from ! from;
this&to ! to;
this&step ! step;
}
public void run() {
for(int i ! from; i +! to; i ,! step)
S-stem&out&print(i , # # );
}
}
public class TestThread1 {
public static void main(String args./) {
)ounter cnt0* cnt1;
cnt0 ! ne" )ounter(2* 022* 3);
cnt1 ! ne" )ounter(022* 122* 02);
ne" Thread( cnt0 )&start();
//lansez primul fir de execuie
ne" Thread( cnt1 )&start();
//lansez al doilea fir de execuie
}
}
1.2. Cic*u* de 1i'2 '* u#ui $ir de execuie
2iecare fir de e,ecuie are propriul s!u ciclu de via!: este creat,
devine activ prin lansarea sa n e,ecuie "i, la un moment dat, se
termin!. Fn continuare vom vedea mai ndeaproape st!rile n care se
poate g!si un fir de e,ecuie. 5iagrama de mai jos din fig.=
ilustreaz! generic aceste st!ri precum "i metodele care provoac!
tranziia dintrCo stare n alta:
:9
2ig.= St!rile firului de e,ecuie
8"adar, un fir de e,ecuie se poate g!si n una din urm!toarele
patru st!ri:
:. Starea J(e' T$readJ
#n fir de e,ecuie se g!se"te n aceast! stare imediat dup! crearea
sa, cu alte cuvinte dup! instanierea unui obiect din clasa Thread
sau dintrCo subclas! a sa.
Thread counterThread ! ne" Thread ( this );
//counterThread se g'se(te An starea %e" Thread
=. Starea J6unnableJ
5up! apelul metodei start un fir de e,ecuie va trece n starea
J6unnableJ, adic! se g!se"te n e,ecuie.
counterThread&start();
//counterThread se g'se(te An starea Runnable
Metoda start realizeaz! urmatoarele operaiuni necesare rul!rii
firului de e,ecuie: aloc! resursele sistem necesare, planific! firul
de e,ecuie la C3# pentru a fi lansat, apeleaz! metoda run a
obiectului reprezentat de firul de e,ecuie.
:>
4. Starea J(ot 6unnableJ
#n fir de e,ecuie ajunge n aceast! stare n una din urmatoarele
situaii:
C este JadormitJ prin apelul metodei sleep;
C a apelat metoda wait, a"tept%nd ca o anumit! condiie
s! fie satisf!cut!E
C este blocat ntrCo operaie de intrareHie"ire.
J8dormireaJ unui fir de e,ecuie
Metoda sleep este o metod! static! a clasei Thread care provoac!
o pauz! n timpul rul!rii firului curent aflat n e,ecuie, cu alte
cuvinte l JadoarmeJ pentru un timp specificat. +ungimea acestei
pauze este specificat! n milisecunde "i c$iar nanosecunde.
public static void sleep( long millis )
thro"s Bnterrupted<xception
public static void sleep( long millis* int nanos )
thro"s Bnterrupted<xception
Fntruc%t poate provoca e,cepii de tipul Bnterrupted<xception
apelul acestei metode se face ntrCun bloc de tip tr-Ccatch:
tr- {
Thread&sleep(0222);
//face pauz' de o secund'
} catch (Bnterrupted<xception e) {
& & &
}&
9. Starea J5eadJ
Iste starea n care ajunge un fir de e,ecuie la terminarea sa. #n fir
de e,ecuie nu poate fi oprit din program printrCo anumit! metod!,
ci trebuie s! se termine n mod natural la terminarea metodei run
pe care o e,ecut!. Terminarea unui fir de e,ecuie folosind o
variabil! de terminare:
import ?ava&io&D;
:<
public class TestThread {
public static void main(String args./) thro"s
BE<xception {
FaitGe- thread ! ne" FaitGe-();
thread&start();
S-stem&in&read();//astept ap'sarea tastei <nter
thread&running ! false;
S-stem&out&println(#SCau scurs # , thread&sec
, # secunde#);
}
}
class FaitGe- extends Thread {
public int sec ! 2;
public boolean running ! true;
//variabila de terminare
public void run() {
"hile ( running ) {
tr- {
Thread&sleep(0222);
sec ,,;
} catch(Bnterrupted<xception e){
}}}}

1.3 3ru+'re' $ire*&r de execuie
Kruparea firelor de e,ecuie pune la dispoziie un mecanism
pentru manipularea acestora ca un tot "i nu individual. 5e e,emplu,
putem s! pornim sau s! suspend!m toate firele dintrCun grup cu un
singur apel de metod!. Kruparea firelor de e,ecuie se realizeaz!
prin intermediul clasei ThreadHroup.
2iecare fir de e,ecuie Java este membru al unui grup, indiferent
dac! specific!m e,plicit acest lucru. 8filierea unui fir de e,ecuie
la un anumit grup se realizeaz! la crearea sa "i devine permanent!,
n sensul c! nu vom putea muta un fir de e,ecuie dintrCun grup n
altul, dup! ce acesta a fost creat. Fn cazul n care cre!m un fir de
:?
e,ecuie f!r! a specifica n constructor din ce grup face parte, el va
fi plasat automat n acela"i grup cu firul de e,ecuie care lCa creat.
+a pornirea unui program Java se creeaz! automat un obiect de tip
ThreadHroup cu numele main, care va reprezenta grupul tuturor
firelor de e,ecuie create direct din program "i care nu au fost
ata"ate e,plicit altui grup. Cu alte cuvinte, putem s! ignoram
complet plasarea firelor de e,ecuie n grupuri "i s! l!s!m sistemul
s! se ocupe cu aceasta, adun%nduCle pe toate n grupul main. I,ist!
situaii c%nd programul creeaz! multe fire de e,ecuie, iar gruparea
lor poate u"ura substanial manevrarea lor. Crearea unui fir de
e,ecuie "i plasarea lui ntrCun grup 0altul dec%t cel implicit1 se
realizeaz! prin urm!torii constructori ai clasei Thread:
public Thread(ThreadHroup group* Runnable target)
public Thread(ThreadHroup group* String name)
public Thread(ThreadHroup group* Runnable target*
String name)
2iecare din ace"ti costructori creeaz! un fir de e,ecuie, l
iniializeaz! "i l plaseaz! ntrCun grup specificat ca argument. Fn
e,emplul urm!tor vor fi create dou! grupuri, primul cu dou! fire de
e,ecuie, iar al doilea cu trei fire de e,ecuie:
ThreadHroup grup0 ! ne" ThreadHroup(#=roducatori#);
Thread p0 ! ne" Thread(grup* #=roducator 0#);
Thread p1 ! ne" Thread(grup* #=roducator 1#);
ThreadHroup grup1 ! ne" ThreadHroup(#)onsumatori#);
Thread c0 ! ne" Thread(grup* #)onsumator 0#);
Thread c1 ! ne" Thread(grup* #)onsumator 1#);
Thread c4 ! ne" Thread(grup* #)onsumator 4#);
3entru a afla c!rui grup aparine un anumit fir de e,ecuie putem
folosi metoda getThreadHroup a clasei Thread. #n grup poate
avea ca p!rinte un alt grup, ceea ce nseamn! c! firele de e,ecuie
pot fi plasate ntrCo ierar$ie de grupuri, n care r!d!cina este grupul
implicit main, ca n fig. 4 de mai jos:
:@
I,emplu: listarea firelor de e,ecuie active
public class <numerateTest {
public void list)urrentThreads() {
ThreadHroup currentHroup !
Thread&currentThread()&getThreadHroup();
//aflu numarul firelor de execuie active
int numThreads ! currentHroup&active)ount();
//pun intrCun vector referine la firele de exec&
//active
Thread./ listEfThreads ! ne" Thread.numThreads/;
currentHroup&enumerate(listEfThreads);
//le afisez pe ecran
for (int i ! 2; i + numThreads; i,,)
S-stem&out&println(#Thread I# , i , # ! # ,
listEfThreads.i/&get%ame());
}
}
Structura de fire de e,ecuie "i grupuri de e,ecuie poate fi
reprezentat! n forma urm!toare:
:;
2ig. 4 Kruparea firelor de e,ecuie
JainHrupa{subHrupa0{subHrupa4{Tha* Thb* Thc* Thd}*
ThK}*subHrupa1{Th0* Th1* Th4}*Th0* Th1}&
4ucr're de *'-&r'"&r #r. 1
1. Te,' *ucr2rii5
Crearea "i enumerarea t$readCurilor
2. 6c&+u* *ucr2rii5
Fnsu"irea modalit!ilor de creare a t$readCurlilor n JavaE
Fnsu"irea metodelor de creare a unui grup de t$readCuriE
3. E"'+e*e de re'*i7're5
10 #tilizarea clasei Thread pentru crearea unei clase noiE
20 #tilizarea interfeei Runnable pentru crearea "i lansarea
de t$readCuriE
30 #tilizarea clasei ThreadGroup pentru crearea grupelor de
t$readCuriE
40 Setarea priorit!ilor t$read/urilor cu setPriority(.);
50 Inumerarea t$readCurilor "i a priorit!ilor lor cu
enumerate()E
60 #tilizare list()E
70 3rezentarea lucr!rii.
4. Exe,+*u de re'*i7're5
public class ThreadHroup0 {
public static void main(String./ args) {
ThreadHroup s-s !
Thread&currentThread()&getThreadHroup();
s-s&list(); // (0)
s-s&setJax=riorit-(Thread&JKLM=RBERBTN C 0);
Thread curr ! Thread&currentThread();
curr&set=riorit-(curr&get=riorit-() , 0);
s-s&list(); // (1)
ThreadHroup g0 ! ne" ThreadHroup(#g0#);
g0&setJax=riorit-(Thread&JKLM=RBERBTN);
=A
Thread t ! ne" Thread(g0* #K#);
t&set=riorit-(Thread&JKLM=RBERBTN);
g0&list(); // (4)
g0&setJax=riorit-(Thread&JKLM=RBERBTN C 1);
g0&setJax=riorit-(Thread&JKLM=RBERBTN);
g0&list(); // (5)
t ! ne" Thread(g0* #O#);
t&set=riorit-(Thread&JKLM=RBERBTN);
g0&list(); // (3)
g0&setJax=riorit-(Thread&JB%M=RBERBTN , 1);
t ! ne" Thread(g0* #)#);
g0&list(); // (6)
t&set=riorit-(t&get=riorit-() C0);
g0&list(); // (7)
ThreadHroup g1 ! ne" ThreadHroup(g0* #g1#);
g1&list(); // (8)
g1&setJax=riorit-(Thread&JKLM=RBERBTN);
g1&list(); // (9)
for (int i ! 2; i + 3; i,,)
ne" Thread(g1* Bnteger&toString(i));
s-s&list(); // (02)
S-stem&out&println(#Starting all threads@#);
Thread./ all ! ne" Thread.s-s&active)ount()/;
s-s&enumerate(all);
for(int i ! 2; i + all&length; i,,)
if(>all.i/&isKlive())
all.i/&start();
6ezultatul rul!rii programului va fi:
(0) ThreadHroup.name!s-stem*maxpri!02/
Thread.main*3*s-stem/
(1) ThreadHroup.name!s-stem*maxpri!9/
Thread.main*6*s-stem/
(4) ThreadHroup.name!g0*maxpri!9/
Thread.K*9*g0/
(5) ThreadHroup.name!g0*maxpri!8/
Thread.K*9*g0/
(3) ThreadHroup.name!g0*maxpri!8/
Thread.K*9*g0/
Thread.O*8*g0/
(6) ThreadHroup.name!g0*maxpri!4/
=:
Thread.K*9*g0/
Thread.O*8*g0/
Thread.)*6*g0/
(7) ThreadHroup.name!g0*maxpri!4/
Thread.K*9*g0/
Thread.O*8*g0/
Thread.)*4*g0/
(8) ThreadHroup.name!g1*maxpri!4/
(9) ThreadHroup.name!g1*maxpri!4/
(02)ThreadHroup.name!s-stem*maxpri!9/
Thread.main*6*s-stem/
ThreadHroup.name!g0*maxpri!4/
Thread.K*9*g0/
Thread.O*8*g0/
Thread.)*4*g0/
ThreadHroup.name!g1*maxpri!4/
Thread.2*6*g1/
Thread.0*6*g1/
Thread.1*6*g1/
Thread.4*6*g1/
Thread.5*6*g1/
Starting all threads@
Kll threads started
5. Pr&-*e,e +r&+u!e5
6ealizarea lucr!rii de laborator nr. : const! din = probleme.3rima
problem! ine de crearea "i e,ecutarea firelor de e,ecuie. 8 doua
problem! se refer! la gruparea "i enumerarea firelor de e,ecuie.
Pr&-*e,' #r.1:
==
Scriei un program care creeaz' doua fire de execuie&
Kmbele fire vor citi datele din acela(i
tablou de date mas./ de tipul int* generat
aleatoriu cu dimensiunea 022 (i ce cuprinde
valori intre 0 (i 022& =rimul fir Th0 va
afi(a@ )ondiie 0 din tabelul 0&
Kl doilea fir Th1 va afi(a@ )ondiie 1 din tabelul 0&
Kpoi dup' terminarea ambelor fire de execuie threadC
ul principal va afi(a informaia despre
studentul care a efectuat lucrarea dat' de
laborator* literele textului vor ap'rea pe
ecran cu un interval de 022 milisecunde&
Tabelul :
Condiii la problema nr. : lHlab nr. :


)ondiie 0 )ondiie 1
: Sumele numerelor pare dou! c%te
dou! ncep%nd c!utarea "i sumarea
de la primul element
Sumele numerelor pare dou! c%te
dou! ncep%nd c!utarea "i sumarea
de la ultimul element
= Suma poziiilor numerelor pare
dou! c%te dou! ncep%nd c!uCtarea
"i sumarea de la primul element
Sumele poziiilor numerelor pare
dou! c%te dou! ncep%nd c!utarea
"i sumarea de la ultimul element
4 Sumele numerelor pare dou! cate
dou! ncep%nd c!utarea "i sumarea
de la primul element
Sumele numerelor pare dou! cate
dou! ncep%nd c!utarea "i sumarea
de la ultimul element
9 Sumele poziiilor numerelor pare
dou! c%te dou! ncep%nd c!utarea
"i sumarea de la primul element
Sumele poziiilor numerelor pare
dou! c%te dou! ncep%nd c!utarea
"i sumarea de la ultimul element
> Sumele produselor numerelor de
pe poziii pare dou! c%te dou!
ncep%nd cu primul element
Sumele produselor numerelor de
pe poziii pare dou! c%te dou!
ncep%nd cu ultimul element
< Sumele produselor numerelor de
pe poziii impare dou! c%te dou!
ncep%nd cu primul element
Sumele produselor numerelor de
pe poziii impare dou! c%te dou!
ncep%nd cu ultimul element
? Sumele produselor numerelor
pare dou! c%te dou! ncep%nd cu
primul element
Sumele produselor numerelor pare
dou! c%te dou! ncep%nd cu ultimul
element
@ Sumele produselor numerelor Sumele produselor numerelor
=4
impare dou! c%te dou! ncep%nd
cu primul element
impare dou! c%te dou! ncep%nd cu
ultimul element
; Sumele numerelor de pe primele
trei poziii pare ncep%nd cu
primul element
Sumele numerelor de pe poziii
pare c%te trei ncep%nd cu ultimul
element
:A 5iferenele produselor numeCrelor
de pe poziii impare c%te dou!
ncep%nd cu primul element
Sumele produselor numerelor de
pe poziii impare dou! cate dou!
ncep%nd cu primul element
Pr&-*e,' #r. 2:
Pe creat o structur'* conform formulei date
An tabelul 1& Pe enumerat toate firele de
execuie din grupa principal' (i subgrupele
ce le conine&
Pe afi(at informaia despre numele firului de
execuie* numele grupei din care face parte*
prioritatea sa& Qn paranteze () *vezi
tabelul 1* se indic' prioritatea fiec'rui
Thread&
Tabelul =

Formula structurii compus! din "ire #i
$rupuri de "ire
: MainLK:LK4LT$a041, T$b041, T$c041, T$d041M,
T$8041M,K=LT$:091, T$=0>1, T$40>1M,T$:0?1, T$=0?1M
= MainLK=LK:LT$a0:1, T$b041, T$c0@1, T$d041M,
T$80:1M,K4LT$:091, T$=041, T$40>1M,T$:041, T$=0<1M
4 MainLK(LKNLT$a091, T$b041, T$c0<1, T$d041M,
T$8041M,KMLT$:0=1, T$=041, T$4041M,T$:0@1, T$=041M
9 MainLKDLKOLT$a0:1, T$b041, T$c041, T$d0?1M,
T$8041M,K2LT$:0>1, T$=041, T$40;1M,T$:041, T$=01M
> MainLKILKNLT$a091, T$b041, T$c0=1, T$d0:1M,
T$8041M,KPLT$:041, T$=0<1, T$4041M,T$:041, T$=0?1M
< MainLK:LK4LT$f041, T$b0?1, T$c041, T$d041M,
T$8041M,K=LT$@041, T$;091, T$4041M,T$:041, T$=041M
? MainLT$8041M,K=LT$:0>1, T$=041, T$440?1M,T$::041,
T$==041, K:LK4LT$aa0=1, T$bb041, T$cc0@1, T$dd041MM
@ MainLK9LK4LT$a0=1, T$b0@1, T$c041, T$d041, K=LT$:041,
T$=041, T$4041, T$8041M,T$:0@1, T$=041MM M
; MainLK<L T$8041M,T$:091, T$=041, K=LT$:0=1,
K4LT$a0=1, T$b041, T$c091, T$d041M, T$=041, T$4041MM
:A MainLK?LK4LT$a0<1, T$b041, T$c0<1, T$d041M,
T$80?1M,T$:0<1, T$=041, K=LT$:0?1, T$=041, T$4041MM
=9
Condiii la problema nr = l H lab. nr. :
PARTEA 2
2.1 Pr&-*e,' +r&duc2"&r 8 c&#!u,'"&r.
6i#cr&#i7're' $ire*&r de execuie
I,ist! numeroase situaii c%nd fire de e,ecuie separate,
dar care ruleaz! concurent, trebuie s! comunice ntre ele pentru a
accesa diferite resurse comune sau pentru aC"i transmite dinamic
rezultatele JmunciiJ lor. Cel mai elocvent scenariu n care firele de
e,ecuie trebuie sa comunice ntre ele este cunoscut sub numele de
problema productorului/consumatorului, n care produc!torul
genereaz! un flu, de date care este preluat "i prelucrat de c!tre
consumator. S! consider!m de e,emplu o aplicaie Java n care un
fir de e,ecuie 0produc!torul1 scrie date ntrCun fi"ier, n timp ce alt
fir de e,ecuie 0consumatorul1 cite"te date din acela"i fi"ier pentru a
le prelucra. Sau, s! presupunem c! produc!torul genereaz! ni"te
numere "i le plaseaz! pe r%nd ntrCun buffer, iar consumatorul
cite"te numerele din acel buffer pentru a le interpreta. Fn ambele
cazuri avem deCa face cu fire de e,ecuie concurente care folosesc
o resurs! comun! : un fi"ier, respectiv un vector "i, din acest motiv,
ele trebuie sincronizate ntrCo manier! care s! permit! decurgerea
normal! a activit!ii lor. 3entru a nelege mai bine modalitatea de
sincronizare a dou! fire de e,ecuie s! implement!m efectiv o
problem! de tip produc!torHconsumator. S! consider!m urm!toarea
situaie:
3roduc!torul genereaz! numerele ntregi de la : la :A,
fiecare la un interval neregulat cuprins ntre A "i :AA de
milisecunde. 3e m!sur! ce le genereaz! ncearc! s! le
=>
plaseze ntrCo zon! de memorie 0o variabil! ntreag!1 de
unde sa fie citite de c!tre consumator.
Consumatorul va prelua, pe r%nd, numerele generate de
c!tre produc!tor "i va afi"a valoarea lor pe ecran.
3entru a fi accesibil!, ambelor fire de e,ecuie, vom ncapsula
variabila ce va conine numerele generate ntrCun obiect descris de
clasa Ouffer "i care va avea dou! metode put 0pentru punerea unui
num!r n buffer1 "i $et 0pentru obinerea num!rului din buffer1.
2!r! a folosi nici un mecanism de sincronizare clasa Quffer arat!
astfel:
class Ouffer {
private int number ! C0;
public int get() {
return number;
}
public void put(int number) {
this&number ! number;
}
}
-om implementa acum clasele 3roduc!tor "i Consumator care vor
descrie cele dou! fire de e,ecuie. 8mbele vor avea o referin!
comun! la un obiect de tip Ouffer prin intermediul c!ruia "i
comunic! valorile.
class %roducator extends Thread {
private Ouffer buffer;
public =roducator(Ouffer b) {
buffer ! b;
}
public void run() {
for (int i ! 2; i + 02; i,,) {
buffer&put(i);
S-stem&out&println(#=roducatorul a pus@Rt#, i);
tr- {
=<
sleep((int)(Jath&random() D 022));
} catch (Bnterrupted<xception e) { }
}
}
}
class &onsumator extends Thread {
private Ouffer buffer;
public )onsumator(Ouffer b) {
buffer ! b;
}
public void run() {
int value ! 2;
for (int i ! 2; i + 02; i,,) {
value ! buffer&get();
S-stem&out&println(#)onsumatorul a
primit@Rt# , value);
}
}
}
//)lasa principal'
public class TestSincronizare0 {
public static void main(String./ args) {
Ouffer b ! ne" Ouffer();
=roducator p0 ! ne" =roducator(b);
)onsumator c0 ! ne" )onsumator(b);
p0&start();
c0&start();
}
}
5upa cum ne a"tept!m, rezultatul rul!rii acestui program nu va
rezolva nici pe departe problema propus! de noi, motivul fiind lipsa
oric!rei sincroniz!ri ntre cele dou! fire de e,ecuie. Mai precis,
rezultatul va fi ceva de forma:
)onsumatorul a primit@ C0
)onsumatorul a primit@ C0
=roducatorul a pus@ 2
)onsumatorul a primit@ 2
)onsumatorul a primit@ 2
)onsumatorul a primit@ 2
=?
=roducatorul a pus@ 0
=roducatorul a pus@ 1
=roducatorul a pus@ 4
=roducatorul a pus@ 5
=roducatorul a pus@ 3
=roducatorul a pus@ 6
=roducatorul a pus@ 7
=roducatorul a pus@ 8
=roducatorul a pus@ 9
8mbele fire de e,ecuie acceseaz! resursa comun!, adic! obiectul
de tip Ouffer, ntrCo manier! $aotic! "i acest lucru se nt%mpl! din
dou! motive :
consumatorul nu a"teapt! nainte de a citi ca produc!torul s!
genereze un num!r "i va prelua de mai multe ori acela"i
num!r.
produc!torul nu a"teapt! consumatorul s! preia num!rul
generat nainte de a produce un altul, n felul acesta
consumatorul va JrataJ cu siguran! unele numere 0n cazul
nostru, aproape pe toate1.
3roblema care se pune n acest moment este: cine trebuie s! se
ocupe de sincronizarea celor dou! fire de e,ecuie : clasele
3roduc!tor "i Consumator sau resursa comun! OufferG
6!spunsul este: resursa comun! Ouffer, deoarece ea trebuie s!
permit! sau nu accesul la coninutul s!u, "i nu firele de e,ecuie
care o folosesc. Fn felul acesta efortul sincroniz!rii este transferat
de la produc!torHconsumator la un nivel mai jos, cel al resursei
critice.
8ctivit!ile produc!torului "i ale consumatorului trebuie
sincronizate la nivelul resursei comune n dou! privine:
:. Cele dou! fire de e,ecuie nu trebuie s! acceseze simultan
bufferCulE acest lucru se realizeaz! prin blocarea obiectului
Ouffer atunci c%nd este accesat de un fir de e,ecuie, astfel
nc%t nici un alt fir de e,ecuie s! nuCl mai poat! accesa.
=@
=. Cele dou! fire de e,ecuie trebuie s! se coordoneze, adic!
produc!torul trebuie s! g!seasc! o modalitate de a JspuneJ
consumatorului c! a plasat o valoare n buffer, iar
consumatorul trebuie s! comunice produc!torului c! a
preluat aceast! valoare, pentru ca acesta s! poat! genera o
alt! valoare. 3entru a realiza aceast! comunicare, clasa
Thread pune la dispoziie metodele wait noti"'
noti"'(ll.
2olosind sincronizarea clasa Ouffer va ar!ta astfel:
class Ouffer {
private int number ! C0;
private boolean available ! false;
public s'nchroni)ed int get() {
"hile (>available) {
tr- {
wait*+;
//a(teapt' producatorul s' pun' o valoare
} catch (Bnterrupted<xception e) { }
}
available ! false;
noti"'(ll();
return number;
}
public s'nchroni)ed void put(int number) {
"hile (available) {
tr- {
wait*+;
//a(teapt' consumatorul s' preia valoarea
} catch (Bnterrupted<xception e) { }
}
this&number ! number;
available ! true;
noti"'(ll();
}
}
6ezultatul obinut va fi cel scontat:
=roducatorul a pus@ 2
=;
)onsumatorul a primit@ 2
=roducatorul a pus@ 0
)onsumatorul a primit@ 0
& & &
=roducatorul a pus@ 9
2.2 9e"&de de !i#cr&#i7're ' "(re'd)uri*&r
2.2.1 :*&c're' u#ui &-iec" /cu1;#"u* c(eie !<#c(r&#i7ed0
Definiie
#n segment de cod ce gestioneaz! o resurs! comun! mai
multor fire de e,ecuie separate "i concurente se nume"te
seciune critic. Fn Java o seciune critic! poate fi un bloc
de instruciuni sau o metod!.
Controlul accesului ntrCo seciune critic! se face prin cuv%ntul
c$eie s'nchroni)ed. 3latforma Java asociaz! un monitor fiec!rui
obiect al unui program ce conine seciuni critice care necesit!
sincronizare. 8cest monitor va indica dac! resursa critic! este
accesat! de vreun fir de e,ecuie sau este liber!, cu alte cuvinte
Jmonitorizeaz!J o resurs! critic!. Fn cazul n care este accesat!, va
Jpune un lac!tJ pe aceasta, astfel nc%t s! mpiedice accesul altor
fire de e,ecuie la ea. Fn momentul c%nd resursa este eliberat!
Jlac!tulJ va fi eliminat pentru a permite accesul altor fire de
e,ecuie.
Fn e,emplul tip produc!torHconsumator de mai sus, seciunile
critice sunt metodele put "i get, iar resursa citic! comun! este
obiectul buffer. Consumatorul nu trebuie s! acceseze bufferCul
c%nd produc!torul tocmai pune o valoare n el, iar produc!torul nu
trebuie sa modifice valoarea din buffer n momentul c%nd aceasta
este citit! de c!tre consumator.
public s'nchroni)ed int get() {
&&&
}
public s'nchroni)ed void put(int number) {
&&&
4A
}
S! observam c! ambele metode au fost declarate cu modificatorul
s-nchronized. Cu toate acestea sistemul asociaz! un monitor unei
instane a clasei Ouffer "i nu unei metode anume. Fn momentul n
care este apelat! o metod! sincron!, firul de e,ecuie care a f!cut
apelul, va bloca obiectul a c!rui metod! o acceseaz!, ceea ce
nseamn! c! celelalte fire de e,ecuie nu vor mai putea accesa
resursele critice, adic! nu vor putea apela nici o metod! sincron!
din acel obiect. 8cesta este un lucru logic, deoarece mai multe
seciuni critice 0metode sincrone1 ale unui obiect gestioneaz!, de
fapt, o singur! resurs! critic!. Fn e,emplul nostru, atunci c%nd
produc!torul apeleaz! metoda put pentru a scrie un num!r, va
bloca tot obiectul de tip Ouffer, astfel ca firul de e,ecuie
consumator nu va avea acces la cealalt! metod! sincron! get, "i
reciproc.
public s-nchronized void put(int number) {
// buffer blocat de produc'tor
&&&
// buffer deblocat de produc'tor
}
public s-nchronized int get() {
// buffer blocat de consumator
&&&
// buffer deblocat de consumator
}
2.2.2 9e"&de*e wait noti"' =i noti"'(ll
Dbiectul de tip Ouffer din e,emplu are o variabil! membr! privat!
numit! number, n care este memorat num!rul pe care l comunic!
produc!torul "i din care l preia consumatorul. 5e asemenea, mai
are o variabil! privat! logic! available, care ne d! starea bufferC
ului: dac! are valoarea true nseamn! c! produc!torul a pus o
valoare n buffer "i consumatorul nu a preluatCo nc!E dac! este
false, consumatorul a preluat valoarea din buffer, dar produc!torul
4:
nu a pus deocamdat! alta la loc. 5eci, la prima vedere metodele
clasei Ouffer ar trebui s! arate astfel:
public s-nchronized int get() {
if (available) {
available ! false;
return number;
}
}
public s-nchronized int put(int number) {
if (>available) {
available ! true;
this&number ! number;
}
}
)mplementate ca mai sus cele dou! metode nu vor funciona corect.
8cest lucru se nt%mpl!, deoarece firele de e,ecuie, de"i "i
sincronizeaz! accesul la buffer, nu se Ja"teapt!J unul pe cel!lalt.
Situaiile n care metodele get "i put nu fac nimic, vor duce la
JratareaJ unor numere de c!tre consumator. 8"adar, cele dou! fire
de e,ecuie trebuie s! se a"tepte unul pe cel!lalt.
public s-nchronized int get() {
"hile (>available) {
//nimic C a(tept ca variabila s' devin' true
}
available ! false;
return number;
}
public s-nchronized int put(int number) {
"hile (available) {
//nimic C a(tept ca variabila s' devin' false
}
available ! true;
this&number ! number;
}
-arianta de mai sus, de"i pare, nu este corect!. 8ceasta, deoarece
implementarea metodelor este Jselfis$J C cele dou! metode "i
a"teapt! n mod egoist condiia de terminare. Ca urmare,
corectitudinea funcion!rii va depinde de sistemul de operare, ceea
4=
ce reprezint! o gre"eal! de programare. 3unerea corect! a unui fir
de e,ecuie n a"teptare se realizeaz! cu metoda "ait a clasei
Thread, care are trei forme:
void "ait( )
void "ait( long timeout )
void "ait( long timeout* long nanos )&
5up! apelul metodei "ait, firul de e,ecuie curent elibereaz!
monitorul asociat obiectului respectiv "i a"teapt! ca una din
urm!toarele condiii s! fie ndeplinit!:
un alt fir de e,ecuie informeaz! pe cei care Ja"teapt!J la un
anumit monitor s! se trezeasc!E acest lucru se realizeaz!
printrCun apel al metodei noti"'(ll sau noti"'.
perioada de a"teptare specificat! a e,pirat.
Metoda "ait poate produce e,cepii de tipul
Bnterrupted<xception, atunci c%nd firul de e,ecuie care
asteapt! 0este deci n starea %ot Runnable1 este ntrerupt din
a"teptare "i trecut forat n starea Runnable, de"i condiia a"teptat!
nu era nc! ndeplinit!. Metoda notif-Kll informeaz! toate firele
de e,ecuie, care sunt n a"teptare la monitorul obiectului curent,
ndeplinirea condiiei pe care o a"teptau. Metoda notif-
informeaz! doar un singur fir de e,ecuie. )at! variantele corecte
ale metodelor get "i put:
public s-nchronized int get() {
"hile (>available) {
tr- {
"ait();
//a(teapt' produc'torul s' pun' o valoare
} catch (Bnterrupted<xception e) { }
}
available ! false;
notif-Kll();
return number;
}
public s-nchronized void put(int number) {
44
"hile (available) {
tr- {
"ait();
//a(teapt' consumatorul s' preia valoarea
} catch (Bnterrupted<xception e) { }
}
this&number ! number;
available ! true;
notif-Kll();
}}
2.2.3 :'riere
Fn aplicaiile multit$reading este necesar ca anumite t$readCuri s!
se sincronizeze la un anumit punct. #n e,emplu este calculul
paralel n faza, n care toate t$readCurile trebuie s!C"i termine faza
de e,ecuie nainte de a trece toate odat! la faza urm!toare. D
-'rier2 este un mecanism folosit pentru a sincroniza mai multe
t$readCuri. #n t$read care nt%lne"te o barier! intr! automat n
"ait()& C%nd ultimul t$read JajungeJ la barier!, semnaleaz!
0notif-()1 celorlalte t$readCuri, care sunt n a"teptare, rezult%nd o
JtrecereJ n grup a barierei. )at! un e,emplu n acest sens:
import ?ava&util&D;
class Oarrier { // )lasa Oarrier sincronizeaz' toi
//participanii private
int =articipatingThreads;
private int FaitingKtOarrier;
public Oarrier(int num){ //)onstructorul
=articipatingThreads ! num;
FaitingKtOarrier!2;
}
public s-nchronized void Reached(){
//Jetoda bariera
FaitingKtOarrier,,;
if(=articipatingThreads >! FaitingKtOarrier){
//Bnseamna ca threadCul nu este ultimul
49
tr- {
"ait(); //ThreadCul este oprit pSn' ce
//este eliberat
} catch (Bnterrupted<xception e) { }
} else { // Kcesta a fost ultimul thread activ
notif-Kll();
FaitingKtOarrier!2;//le elibereaz' pe toate
}
}
}
8jung%nd la barier! toate t$readCurile, mai puin ultimul, asteapt!
n interiorul metodei sync$ronized ca ultimul t$read ajuns s! le
elibereze. Ddat! ce sCau JtrezitJ ei intr! n competiie pentru
monitor "i unul dintre ei l c%"tig!, apoi iese imediat eliber%nd
monitorul. Celelalte t$readCuri continu! s! concureze pentru
acest monitor "i s!Cl elibereze p%n! ce ultimul t$read face acest
lucru "iCn acest moment sunt cu toii JliberiJ. Fn acest e,emplu am
presupus c! se cunoa"te dinainte num!rul de t$readCuri
participante. 5ac!, ns!, acest num!r nu este cunoscut dinainte
poate fi aplicat un mecanism de nregistrare a participanilor.
Drice t$read care dore"te s! a"tepte la barier!, mai nt%i trebuie s!
se JnregistrezeJ increment%nd numarul de t$readCuri n a"teptare.
5e unde "tim c! toate t$readCurile care a"teapt! la barier! sCau
nregistratG Ce se nt%mpl! dac! toate t$readCurile, mai puin unul,
"iCau terminat de f!cut calculele "i ultimul t$read 0care, probabil,
nici nu a fost planificat s! ruleze nc!1 nu sCa nregistrat nc!. Toate
celelalte t$readCuri vor trece bariera ne"tiind c! trebuie s!Cl
a"tepte "i pe acesta din urm!.
2.2.4 6e,'$&'re
Java are aceast! sincronizare cu monitoare, dar poate utiliza
"i semafoare. #tilizind monitoare, se poate implementa orice obiect
4>
sincronizat dorit, inclusiv !e,'$&'re. )at! n continuare un
e,emplu de semafor n Java:
class Semaphore {
protected int value;
Semaphore( int initialTalue ) {
value ! initialTalue;
}
Semaphore() {
value ! 2;
}
public s-nchronized void Het() {
"hile (value+0)
"ait();
valueCC;
}
public s-nchronized void =ut() {
value,,;
notif-();
}
}
4ucr're de *'-&r'"&r #r. 2
1. Te,' *ucr2rii5
Sincronizarea t$readCurilor n Java.
2. 6c&+u* *ucr2rii5
Fnsu"irea metodelor de sincronizare a t$readCurilor
3. E"'+e*e de re'*i7're5
:1 #tilizarea clasei Thread pentru crearea unei clase noiE
=1 #tilizarea interfeei Runnable pentru crearea "i lansarea
de t$readCuriE
41 )mplementarea clasei produc!torE
91 )mplementarea clasei consummatorE
4<
>1 Sincronizarea t$readCurilor prin diferite metode:
a1 utiliz%nd variabile logiceE
b1 utiliz%nd monitoare 0s-nchronized1.
4. Exe,+*u de re'*i7're5
Trebuie s! includ! clasa 3roduc!tor, Consumator cu
sin$ronizarea respectiv!
public class =roducer extends Thread {
private )ubb-Uole cubb-hole;
private int number;
public =roducer()ubb-Uole c* int number) {
cubb-hole ! c;
this&number ! number;
}
public void run() {
for (int i ! 2; i + 02; i,,) {
cubb-hole&put(i);
S-stem&out&println(#=roducer I# ,
this&number , # put@ # , i);
tr- {
sleep((int)(Jath&random() D 022));
} catch (Bnterrupted<xception e) { }
}
}
}
public class )onsumer extends Thread {
private )ubb-Uole cubb-hole;
private int number;
public )onsumer()ubb-Uole c* int number) {
cubb-hole ! c;
this&number ! number;
}
public void run() {
int value ! 2;
for (int i ! 2; i + 02; i,,) {
value ! cubb-hole&get();
4?
S-stem&out&println(#)onsumer I# ,
this&number , # got@ # , value);
}
}
}
public class =roducer)onsumerTest {
public static void main(String./ args) {
)ubb-Uole c ! ne" )ubb-Uole();
=roducer p0 ! ne" =roducer(c* 0);
)onsumer c0 ! ne" )onsumer(c* 0);
p0&start();
c0&start();
}
}
5. Pr&-*e,e +r&+u!e5
* produc!tori genereaz! aleatoriu 2 obiecte care sunt
consumate de R consumatori. 5e afi"at informaia despre
producerea "i consumarea obiectelor, mesajele despre cazurile
c%nd Sdepozitul e gol sau plinT. Toate operaiile se efectueaz!
p%n! c%nd fiecare consumator este ndestulat cu O obiecte.
5imensiunea depozitului este 5. -alorile se iau din tabelul 4
Tabelul 4
5ate iniiale pentru problem! la lHlab nr. 4
(r. * R O 5 Tip Dbiecte
:
= 4 :: @
(umere pare
=
4 9 = >
(umere impare
4
9 4 4 :A
-ocale
9
4 = := ::
Consoane
>
= > 4 :=
(umere pare
<
= 9 9 ?
(umere impare
?
4 4 > <
-ocale
@
9 = 9 >
Consoane
;
> = 4 9
(umere pare
4@
:A
4 4 > =
(umere impare
7 fiecare produc!tor poate produce c%te = obiecte de fiecare
dat!
PARTEA 3

3.1 A++*e")uri
3.1.1 Ce e!"e u# '++*e" %
Definiie
#n applet reprezint! o suprafa! de afi"are 0container1 ce
poate fi inclus! ntrCo pagin! &eb "i gestionat! printrCun
program Java. #n astfel de program se mai nume"te
miniaplicaie sau, prin abuz de limbaj, applet.
Codul unui applet poate fi format din una sau mai multe clase. #na
dintre acestea este principal "i e,tinde clasa Kpplet, fiind clasa ce
trebuie specificat! n documentul NTM+ ce descrie pagina de &eb
n care dorim s! includem appletul.
5iferena fundamental! dintre un applet "i o aplicaie const! n
faptul c! un applet nu poate fi e,ecutat independent, ci va fi
e,ecutat de bro'serul n care este nc!rcat! pagina &eb, ce conine
appletul respectiv. D aplicaie independent! este e,ecutat! prin
apelul interpretorului java, av%nd ca parametru numele clasei
principale a aplicaiei, clasa principal! fiind cea, care conine
metoda main. Ciclul de via! al unui applet este complet diferit,
fiind dictat de evenimentele generate de c!tre bro'ser la
vizualizarea documentului NTM+, ce contine appletul. 3ac$etul
care ofer! suport pentru creearea de appleturi este ?ava&applet.
3.1.2 Cre're' u#ui '++*e"
4;
Drice applet este implementat prin crearea unei subclase a clasei
Kpplet. )erar$ia claselor din care deriv! Kpplet este prezentat! n
fig. 9:
2iind derivat! din clasa )ontainer, clasa Kpplet descrie de fapt
suprafee de afi"are, asemenea claselor ;rame sau =anel.
U# '++*e" !i,+*u
import ?ava&applet&Kpplet;
import ?ava&a"t&D;
public class KppletSimplu extends Kpplet {
public void paint(Hraphics g) {
g&set;ont(ne" ;ont(#Krial#*
;ont&OEVP* 06));
g&dra"String(#Uello#* 2* 42);
}
}
#zual, clasa principal! va fi salvat! ntrCun fi"ier cu acela"i nume "i
e,tensia &?ava. 8sadar, vom salva clasa de mai sus ntrCun fi"ier
KppletSimplu&?ava.

9A
2ig. 9 )erar$ia claselor din care provine clasa Kpplet
Execui' /1i7u'*i7're'0
3entru a vizualiza acest applet trebuie s! cre!m un document
NTM+, s!Ci spunem demo&html, n care s! specific!m cel puin
urmatoarele informaii:
clasa ce contine codul appletuluiE
l!imea "i n!limea suprafeei alocate pe pagina &eb
+UTJVW
+U<KPW+TBTV<W Xn applet simplu +/TBTV<W
+/U<KPW
,(%%-.T &/0.12(pplet3implu4class2 560T71100
7.687T1509,:(%%-.T9
+/UTJVW
-izualizarea acestui document se poate face cu orice bro'ser
0)nternet I,plorer, (etscape, etc1, sau cu utilitarul appletvie"er
ce vine n pac$etul J5P.
appletvie"er demo&html
3.1.3 6"ruc"ur' >e#er'*2 ' u#ui '++*e"
import ?ava&applet&Kpplet;
import ?ava&a"t&D;
import ?ava&a"t&event&D;
public class StructuraKpplet extends Kpplet {
public void init() {
}
public void start() {
}
public void stop() {
}
public void destro'*+ {
9:
}
public void paint(Hraphics g) {
}
}
3.1.4 De$i#ire' =i $&*&!ire' +'r',e"ri*&r
3arametrii sunt pentru appleturi ceea ce argumentele de la linia de
comand! sunt pentru aplicaiile independente. Ii permit
utilizatorului s! personalizeze aspectul sau comportarea unui applet
f!r! aCi sc$imba codul "i recompila clasele.
De$i#ire' parametrilor se face n cadrul tagului 833+IT din
documentul NTM+ ce conine appletul "i sunt identificai prin
atributul PARA9. 2iecare parametru are un nume, specificat prin
NA9E "i o valoare, specificat! prin .A4UE, ca n e,emplul de
mai jos:
+K==V<T )EP<!#KppletSimplu&class# FBPTU!022 U<BHUT!32
+=KRKJ %KJ<!textKfisat TKVX<!#Salut#W
+=KRKJ %KJ<!nume;ont TKVX<!#Times %e" Roman#W
+=KRKJ %KJ<!dim;ont TKVX<!12W
+/K==V<TW
2olosirea parametrilor primii de c!tre un applet se face prin
intermediul metodei get=arameter care prime"te ca argument
numele unui parametru "i returneaz! valoarea acestuia. Fn cazul n
care nu e,ist! nici un parametru cu numele specificat, metoda
ntoarce null, caz n care programul trebuie s! atribuie o valoare
implicit! variabilei n care se dorea citirea respectivului parametru.
S! rescriem appletul considerat iniial 0KppletSimplu1, astfel nc%t
acesta s! afi"eze te,tul primit ca parametru, folosind un font cu
numele "i dimensiunea specificate de asemenea ca parametri.
import ?ava&applet&Kpplet;
import ?ava&a"t&D;
9=
public class KppletSimplu extends Kpplet {
String text* nume;ont;
int dim;ont;
public void init() {
text 1 $et%arameter*2text("isat2+;
if (text!!null)
text!#Uello#; // valoare implicit'
nume;ont ! get=arameter(#nume;ont#);
if (nume;ont!!null)
nume;ont!#Krial#;
tr- {
dim;ont !
Bnteger&parseBnt(get=arameter(#dim;ont#));
} catch(%umber;ormat<xception e) {
dim;ont ! 06;
}
}
public void paint(Hraphics g) {
g&set;ont(ne" ;ont(nume;ont* ;ont&OEVP*dim;ont));
g&dra"String(text* 12* 12);
}
}
3.2 F&*&!ire' $ire*&r de execuie ?# '++*e"uri
2iecare applet aflat pe o pagin! &eb se e,ecut! ntrCun fir de
e,ecuie propriu. 8cesta este creat de c!tre bro'ser "i este
responsabil cu desenarea appletului 0apelul metodelor update "i
paint1 precum "i cu transmiterea mesajelor generate de c!tre
componentele appletului. Fn cazul n care dorim s! realiz!m "i alte
operaiuni consumatoare de timp, este recomandat s! le realiz!m
ntrCun alt fir de e,ecuie, pentru a nu bloca interaciunea
utilizatorului cu appletul sau redesenarea acestuia.
Structura unui applet care dore"te s! lanseze un fir de
e,ecuie poate avea dou! forme. Fn prima situaie appletul porne"te
94
un fir de e,ecuie la iniializarea sa, iar acesta va rula, indiferent
dac! appletul mai este sau nu vizibil, p%na la oprirea sa natural!
0terminarea metodei run1
import ?ava&applet&Kpplet;
class KppletThread0 extends Kpplet implements Runnable
{
Thread appletThread ! null;
public void init() {
if (appletThread !! null) {
appletThread ! ne" Thread(this);
appletThread&start();
}
}
public void run() {
//codul firului de execuie
}
}
Fn cazul n care firul de e,ecuie pornit de applet efectueaz!
operaii ce au sens doar dac! appletul este vizibil, cum ar fi
animaie, ar fi de dorit ca acesta s! se opreasca atunci c%nd appletul
nu mai este vizibil 0la apelul metodei stop1 "i s! reporneasc! atunci
c%nd appletul redevine vizibil 0la apelul metodei start1.
import ?ava&applet&Kpplet;
public class StructuraKpplet extends Kpplet implements
Runnable {
Thread appletThread ! null;
boolean running ! false;
public void start() {
//reporne(ste firul de execuie
if (appletThread !! null) {
appletThread ! ne" Thread(this);
running ! true;
appletThread&start();
}
}
99
public void stop() {
//opre(te firul de execuie
running ! false;
appletThread ! null;
}
public void run() {
"hile (running) {
//codul firului de execuie
}
}
}
#n applet este considerat activ imediat dup! apelul metodei start
"i devine inactiv la apelul metodei stop. 3entru a afla dac! un
applet este activ se folose"te metoda isKctive.
4ucr're de *'-&r'"&r #r. 3
1. Te,' *ucr2rii5
8nimaia appleturilor cu ajutorul t$readCurilor.
2. 6c&+u* *ucr2rii5
Fnsu"irea modalit!ilor de creare a appletelor n JavaE
Fnsu"irea metodelor de utilizare a t$readCurilor n applete
pentru animare.
3. E"'+e*e de re'*i7're5
:1 #tilizarea clasei Thread pentru crearea unei clase noiE
=1 #tilizarea interfeei Runnable pentru crearea "i lansarea
de t$readCuriE
41 Crearea paginii html ce include tagurile appletE
91 #tilizare a parametrilor din applet n e,ecutarea
appletuluiE
9>
>1 #tilizare a buferiz!rii duble pentru animaia appletului,
utiliz%nd t$readCurile.
4. Exe,+*u de re'*i7're5
Te,tul din parametrii paginii html se va deplasa pe suprafaa
appletului.
import ?ava&a"t&Hraphics;
import ?ava&a"t&;ont;
import ?ava&a"t&Bmage;
import ?ava&a"t&Rectangle;
public class ScrollText extends ?ava&applet&Kpplet
implements Runnable{
int h;
int ";
char separated./;
String s!null;
String hs!null;
String "s!null;
Thread Yillme!null;
int speed!43;
boolean threadSuspended!false;
int dist;
Bmage offscreenBmage;
Hraphics offscreenHraphics;
public void init(){
"s!get=arameter(#"idth#);
hs!get=arameter(#height#);
if("s!!null){
"!032;
}else{
"!Bnteger&parseBnt("s);
}
if(hs!!null){
h!32;
}else{
h!Bnteger&parseBnt(hs);
}
9<
resize("*h);
s!get=arameter(#text#);
if(s!!null)
s!#The $ava ScrollText at "orY&#;
separated !ne" char.s&length()/;
s&get)hars(2*s&length()*separated* 2);
offscreenBmage!createBmage("*h);
offscreenHraphics!offscreenBmage&getHraphics();
offscreenHraphics&set;ont(ne"
;ont(#TimesRoman#*;ont&OEVP*hC1));
}
public void start(){
if(Yillme!!null){
Yillme!ne" Thread(this);
Yillme&start();
}
}
public void stop(){
Yillme!null;
}
public void run(){
"hile(Yillme>!null){
tr-{
Thread&sleep(speed);
}catch(Bnterrupted<xception "){}
scroll();
M
Yillme!null;
}
s-nchronized void scroll(){
distCC;
if(dist,((s&length(),0)D(hD3/00))!!2)
dist!";
repaint();
}
public void paint(Hraphics g){
Rectangle r!bounds();
9?
offscreenHraphics&clearRect(2*2*r&"idth*
r&height);
offscreenHraphics&dra")hars(separated*2*s&length()*
dist*5Dh/3);
g&dra"Bmage(offscreenBmage*2*2*this);
}
public void update(Hraphics g){
paint(g);
}
public boolean mousePo"n(?ava&a"t&<vent evt* int
x* int -){
if(threadSuspended){
Yillme&resume();
}else{
Yillme&suspend();
}
threadSuspended!>threadSuspended;
return true;
}
}
C&#i#u"u* $i=ieru*ui @T94 +e#"ru ?#c2rc're' '++*e"u*ui5
+htmlW
+headW+titleWScrollText+/titleW+/headW
+bod-W
+applet code!#ScrollText&class#
align!#middle# "idth!#032# height!#32#
vspase!#03# hspase!#3#W +pWKr trebui sa
fie applet +/pW +/appletW+brW
+applet
code!ScrollText&class "idth!032 height!32W
+/appletW
+/bod-W
+/htmlW
9@
5. Pr&-*e,e +r&+u!e5
5e scris un program pentru realizarea unui applet ce va utiliza
firele de e,ecuie pentru realizarea:
:. Ceas, ce poate fi setat "i restartat prn clicB 0 prefaa
unei emisiuni T-1E
=. Cronometru, cu butoanele startHstop "i resetE
4. Kenerare de figuri geometrice ce se mi"c!, ce pot fi
create sau distruse ap!s%nd pe butonul ce corespunde
figuriiE
9. Joc de calculator tetris cu = figuri de tipul StetrisT
utiliz%nd tastatura, n care pot fi = participaniE
>. Componenta te,t ce "i sc$imba umbrele n
dependen! de mi"carea sursei de lumin!E
<. )mage loader, applet ce afi"eaz! un "ir de imagini, n
timp ce se poate de scris te,t n Te,t8reaE
?. Spot publicitar, ce poate fi ntrerupt "i repornit, ce
caracterizeaz! 2C)ME
@. Spot publicitar ce poate fi ntrerupt "i repornit, ce
caracterizeaz! Catedra CalculatoareE
;. Spot publicitar ce poate fi ntrerupt "i repornit, ce
caracterizeaz! Cursul JavaE
:A. Component!, ce poate fi intrerupt! "i repornit!, ce
reprezint! mi"carea planetelor n sistemul solar, ca o parte
a unui applet, ce ar permite listarea imaginilor n acela"i
timp de c!tre utilizator.
9;
PARTEA 4
4.1 Ce !u#" $*uxuri*e%
8deseori programele necesit! citirea unor informaii care se g!sesc
pe o surs! e,tern! sau trimiterea unor informaii c!tre o destinaie
e,tern!. )nformaia se poate g!si oriunde: ntrCun fi"ier pe disc, n
reea, n memorie sau n alt program "i poate fi de orice tip: date
primitive, obiecte, imagini, sunete, etc. 3entru a aduce informaii
dintrCun mediu e,tern, un progam Java trebuie s! desc$id! un
canal de comunicaie (flux) c!tre sursa informaiilor 0fi"ier,
memorie, socBet, etc1 "i s! citeasc! serial informaiile respective,
cum e ar!tat n fig.>.

Similar, un program poate trimite informaii c!tre o destinaie
e,tern! desc$iz%nd un canal de comunicaie 0flu,1 c!tre acea
destinaie "i scriind serial informaiile respective, vezi fig.<.
>A
2ig. >. 2lu, de citire
)ndiferent de tipul informaiilor, citireaHscrierea informaiilor de
peHc!tre un mediu e,tern respect! urm!torii algoritmi:
Ci"ire' 6criere'
deschide canal comunicaie
"hile (mai sunt
informaii) {
cite(te informaie
}
inchide canal comunicaie
deschide canal comunicaie
"hile (mai sunt informaii)
{
scrie informaie
}
inchide canal comunicaie
3entru a generaliza at%t sursa e,tern! a unor informaii, c%t "i
destinaia lor sunt v!zute ca fiind ni"te procese care produc,
respectiv consuma informaii:
#n flux este un canal de comunicaie unidirecional ntre dou!
procese. 2lu,urile sunt canale de comunicaie seriale pe @ sau :<
bii. 2lu,urile sunt unidirecionale, de la produc!tor la consumator.
Clasele "i intefeele standard pentru lucu cu flu,uri se g!sesc n
pac$etele ;a<a4io ;a<a4nio4
9e"&de c&,u#e $*uxuri*&r
Superclasele abstracte Reader "i BnputStream definesc metode
similare pentru citirea datelor:
>:
2ig. <. 2lu, de scriere
Re'der I#+u"6"re',
int read()
int read(char buf./)
int read(char buf./* int
offset*int length)
int read()
int read(b-te buf./)
int read(b-te buf./* int
offset*int length)
5e asemenea ambele clase pun la dispoziie metode pentru
marcarea unei locaii ntrCun flu,, saltul peste un num!r de poziii,
resetarea poziiei curente, etc. Superclasele abstracte Friter "i
EutputStream sunt de asemenea paralele, definind metode similare
pentru scrierea datelor.
Ari"er Ou"+u"6"re',
int "rite()
int "rite(char buf./)
int "rite(char buf./*
int offset*int length)
int "rite()
int "rite(b-te buf./)
int "rite(b-te buf./* int
offset*int length)
Fnc$iderea oric!rui flu, se realizeaz! prin metoda close. Fn cazul
n care aceasta nu este apelat! e,plicit, flu,ul va fi automat nc$is
de catre colectorul de gunoaie, atunci c%nd nu va mai e,ista nici o
referin! la el.Metodele referitoare la flu,uri pot genera e,cepii de
tipul BE<xception.
4.1.1 Cre're' u#ui $*ux
Drice flu, este un obiect al clasei ce implementeaz! flu,ul
respectiv. Crearea unui flu, se realizeaz! similar cu crearea
obiectelor prin instruciunea ne"*+.
<xemple@
>=
//crearea unui flux de intrare pe caractere
;ileReader An ! ne"
;ileReader(#fi(ierMintrare&txt#);
//crearea unui flux de ie(ire pe caractere
;ileFriter out ! ne"
;ileFriter(#fi(ierMiesire&txt#);
//crearea unui flux de intrare pe octeti
;ileBnputStream An ! ne"
;ileBnputStream(#fi(ierMintrare&txt#);
//crearea unui flux de ie(ire pe octeti
;ileEutputStrem out ! ne"
;ileEutputStream(#fi(ierMiesire&txt#);
Crearea unui flu, primitiv de date care scrieHcite"te informaii de la
un dispozitiv e,tern are formatul general:
;lux=rimitiv nume;lux ! ne"
;lux=rimitiv( dispozitiv extern)
2lu,urile de procesare nu pot e,ista de sine st!t!toare, ci se
suprapun pe un flu, primitiv de citireHscriere a datelor. 5in acest
motiv, constructorii claselor pentru flu,urile de procesare nu
primesc ca argument un dispozitiv e,tern de memorare a datelor, ci
o referin! la un flu, primitiv responsabil cu citireaHscrierea
efectiv! a datelor:
<xemple@
//crearea unui flux de intrare printrCun buffer
OufferedReader An ! ne" OufferedReader(ne"
;ileReader(#fi(ier&in#));
//echivalent cu
;ileReader fr ! ne" ;ileReader(#fi(ier&in#);
OufferedReader An ! ne" OufferedReader(fr);
//crearea unui flux de ie(ire printrCun buffer
>4
OufferedFriter out ! ne" OufferedFriter(ne"
;ileFriter(#fi(ier&out#)));
//echivalent cu
;ileFriter fo ! ne" ;ileFriter(#fi(ier&out#);
OufferedFriter out ! ne" OufferedFriter(fo);
Crearea unui flu, pentru procesarea datelor are formatul general:
;lux=rocesare nume;lux ! ne" ;lux=rocesare(
referinta;lux=rimitiv);
)n general, flu,urile pot fi grupate n succesiuni oric%t de lungi:
PataBnputStream An !
ne" PataBnputStream(
ne" OufferedBnputStream(
ne"
;ileBnputStream(#fi(ier&in#)));
4.1.2 F*uxuri +e#"ru *ucru* cu $i=iere /$*uxuri de "i+ ;ile0
2lu,urile pentru lucrul cu fi"iere sunt cele mai u"or de neles.
Clasele care implementeaz! aceste flu,uri sunt urm!toarele:
;ileReader* ;ileFriter = caractere
;ileBnputStream* ;ileEutputStream = octe>i
Constructorii acestor clase accept! ca argument un obiect care s!
specifice un anume fi"ier. 8cesta poate fi un "ir de caractere, un
obiect de tip ;ile sau un obiect de tip ;ilePesciptor.
Constructorii clasei ;ileReader:
public ;ileReader( String file%ame ) thro"s
;ile%ot;ound<xception
public ;ileReader( ;ile file ) thro"s
;ile%ot;ound<xception
>9
public ;ileReader( ;ilePescriptor fd )
Constructorii clasei ;ileFriter:
public ;ileFriter( String file%ame ) thro"s
BE<xception
public ;ileFriter( ;ile file ) thro"s
BE<xception
public ;ileFriter( ;ilePescriptor fd )
public ;ileFriter( String file%ame*
boolean append ) thro"s BE<xception
Cei mai uzuali constructori sunt cei care primesc ca argument
numele fi"ierului. 8ce"tia pot provoca e,cepii de tipul
;ile%ot;ound<xception n cazul, n care fi"ierul cu numele
specificat nu e,ist!. 5in acest motiv, orice creare a unui flu, de
acest tip trebuie f!cut! ntrCun bloc tr- sau metoda n care sunt
create flu,urile respective trebuie s! arunce e,cepiile de tipul
;ile%ot;ound<xception sau de tipul superclasei BE<xception.
<xemplu@ un program care copie coninutul unui fi(ier
An alt fi(ier@
import ?ava&io&D;
public class )op- {
public static void main(String./ args) thro"s
BE<xception {
;ileReader An ! ne"
;ileReader(#in&txt#);
;ileFriter out ! ne"
;ileFriter(#out&txt#);
int c;
"hile ((c ! in&read()) >! C0)
out&"rite(c);
in&close();
>>
out&close();
}
}
Ebs@ metoda main arunca excepii BE<xception
care este superclasa pentru
;ile%ot;ound<xception& Kceste excepii nu vor fi
#prinse#* decSt de Anterpretor (i va fi afi(at
un mesa? de eroare la apariia lor&
Cele mai importante clase din aceast! categorie sunt
PataBnputStream "i PataEutputStream .
4.1.3 Ci"ire' d'"e*&r de *' "'!"'"ur2
#zual, vom dori s! folosim metoda readVine pentru citirea datelor
de la tastatur! "i din acest motiv vom folosi intrarea standard
mpreun! cu o clas! de procesare care implementeaz! metoda
readVine. I,emplul tipic este:
OufferedReader stdin ! ne" OufferedReader(ne"
BnputStreamReader(S-stem&in));
S-stem&out&print(#Bntroduceti o linie@#);
String linie ! stdin&readVine()
S-stem&out&println(linie);
I,emplu: un program care afiseaz! liniile introduse de la tastatur!
import ?ava&io&D;
public class <cho {
public static void main(String./ args) {
OufferedReader stdin ! ne" OufferedReader(ne"
BnputStreamReader(S-stem&in));
String s;
tr- {
"hile((s ! stdin&readVine())&length() >! 2)
S-stem&out&println(s);
><
//=rogramul se opreste cu o linie vida
} catch(BE<xception e) {
e&printStacYTrace();
}
}
}
4.1.4 A#'*i7' *exic'*2 +e $*uxuri /c*'!' 3treamTo?eni)er0
Clasa StreamToYenizer parcurge un flu, de intrare de orice tip "i
l mparte n Jatomi le,icaliJ. 6ezultatul va consta n faptul c! n
loc s! se citeasc! octei sau caractere, se vor citi, pe r%nd, atomii
le,icali ai flu,ului respectiv.
3rintrCun atom le,ical se nelege n general:
o un identificator 0un "ir care nu este ntre g$ilimele1E
o un num!rE
o un "ir de caractereE
o un comentariuE
o un separator.
8tomii le,icali sunt desp!rii ntre ei de separatori. )mplicit ace"ti
separatori sunt cei obi"nuii 0spaiu, tab, virgul!, punct "i virgul!1,
ns! pot fi sc$imbai prin diverse metode ale clasei.
Constructorii acestei clase sunt:
public StreamToYenizer( Reader r )
public StreamToYenizer( BnputStream is )
)dentificarea tipului "i valorii unui atom le,ical se face prin
intermediul variabilelor:
TTM<E; C atom ce marcheaz' sfSrsitul fluxului
>?
TTM<EV C atom ce marcheaz' sfSrsitul unei linii
TTM%XJO<R C atom de tip numar
TTMFERP C atom de tip cuvSnt
nval C valoarea unui atom numeric
sval C (irul coninut de un atom de tip cuvSnt
tt-pe C tipul ultimului atom citit din flux
Citirea atomilor din flu, se face cu metoda nextToYen, care
returneaz! tipul atomului le,ical citit "i scrie n variabilele nval sau
sval valoarea corespunz!toare atomului. I,emplul tipic de folosire
a unui analizator le,ical este citirea unei secvene de numere "i
"iruri aflate ntrCun fi"ier sau primite de la tastatur!:
//)itirea unei secvene de numere (i (iruri
import ?ava&io&D;
public class TestToYenizer {
public static void main(String args./) thro"s
BE<xception{
;ileBnputStream fis ! ne"
;ileBnputStream(#test&dat#);
OufferedReader br ! ne" OufferedReader(ne"
BnputStreamReader(fis));
StreamToYenizer st ! ne" StreamToYenizer(br);
int tip ! st&nextToYen();
//citesc primul atom lexical
"hile (tip >! StreamToYenizer&TTM<E;) {
s"itch (tip) {
case StreamToYenizer&TTMFERP @//cuvSnt
S-stem&out&println(st&sval);
breaY;
case StreamToYenizer&TTM%XJO<R @//numar
S-stem&out&println(st&nval);
}
tip ! st&nextToYen();//urm'torul atom
}
}
}
>@
8sadar, modul de utilizare tipic pentru un analizator le,ical este
ntrCo bucl! J'$ileJ n care se citesc atomii unul c%te unul cu
metoda nextToYen p%n! se ajunge la sf%r"itul flu,ului 0TTM<E;1. Fn
cadrul buclei J'$ileJ se afl! tipul atomul curent0ntors de metoda
nextToYen1 "i apoi se afl! valoarea numeric! sau "irul de caractere,
corespunz!tor atomului respectiv. #n e,emplu mai simplu de
folosire 0dar nepractic1 ar fi citirea unui ntreg sau a unui "ir de
caractere de la tastatur!:
//)itirea unui Antreg de la tastatur'
import ?ava&io&D;
public class TestReadBn {
public static void main(String args./) {
tr-{
Reader r ! ne"
BnputStreamReader(S-stem&in);
StreamToYenizer st ! ne"
StreamToYenizer(r);
S-stem&out&print(#n!#);
int tip ! st&nextToYen();
S-stem&out&println(#Taloarea lui n este
# , (int)st&nval);
}
catch (BE<xception e) {}
}
}
4.1.5 C*'!' File
Clasa ;ile are un nume n"el!tor, ntruc%t ea nu se refer! doar la
un fi"ier, ci poate reprezenta fie un fi"ier anume, fie mulimea
fi"ierelor dintrCun director. D instan! a acestei clase poate s!
reprezinte: un fi"ier sau un director. Specificarea unui fi"ierHdirector
se face prin specificarea c!ii absolute spre acel fi"ier sau a c!ii
>;
relative fa! de directorul curent. 8cestea trebuie s! respecte
conveniile de specificare a c!ilor "i numelor fi"ierelor de pe
ma"ina gazd!. #tilitatea clasei ;ile const! n furnizarea unei
modalit!i de a abstractiza dependenele c!ilor "i numelor fi"ierelor
fa! de ma"ina gazd!, precun "i punerea la dispoziie a unor metode
pentru lucrul cu fi"iere "i directoare la nivelul sistemului de
operare. 8stfel, n aceast! clas! vom g!si metode pentru testarea
e,istenei, "tergerea, redenumirea unui fi"ier sau director, crearea
unui director, listarea fi"ierelor dintrCun director, etc.
Trebuie menionat "i faptul c!, majoritatea constructorilor
flu,urilor, care permit accesul la fi"iere, accept! ca argument un
obiect de tip ;ile n locul unui "ir ce reprezint! numele fi"ierului
accesat.
;ile fMin ! ne" ;ile(#fi(ier&txt#);
;ileBnputStream stMin ! ne" ;ileBnputStream(fMin)&
4.2 Pr&>r','re' ?# ree'
4.2.1 N&iu#i >e#er'*e de!+re ree*e
3rogramarea n reea implic! trimiterea de mesaje "i date ntre
aplicaii ce ruleaz! pe calculatoare aflate ntrCo reea local! sau
conectate la )nternet. 3ac$etul care ofer! suport pentru scrierea
aplicaiilor de reea este ?ava&net. Clasele din acest pac$et ofer! o
modalitate facil! de programare n reea, f!r! a fi nevoie de
cuno"tine prealabile referitoare la comunicarea efectiv! ntre
calculatoare. Cu toate acestea sunt necesare c%teva noiuni
fundamentale referitoare la reele, cum ar fi protocol, adresa )3,
port, socBet.
<A
4.2.2 Ce e!"e u# +r&"&c&* %
#n protocol reprezint! o convenie de reprezentare a datelor
folosit! n comunicarea ntre dou! calculatoare. 8v%nd n vedere
faptul ca orice informaie care trebuie trimis! prin reea trebuie
serializat!, astfel nc%t s! poat! fi transmis! secvenial, octet cu
octet, c!tre destinaie, era nevoie de stabilirea unor convenii
0protocoale1 care s! fie folosite at%t de calculatorul care trimite
datele, c%t "i de cel care le prime"te.
Cele mai utilizate protocoale sunt TCP "i UDP.
Definiii
TC (Transport Control rotocol) este un protocol ce
furnizeaz! un flu, sigur de date ntre dou! calculatoare.
8cest protocol asigur! stabilirea unei cone,iuni permanente
ntre cele dou! calculatoare pe parcursul comunicaiei.
!D (!ser Datagram rotocol) este un protocol ce trimite
pac$ete independente de date, numite datagrame, de la un
calculator c!tre altul f!r! a garanta n vreun fel ajungerea
acestora la destinaie. 8cest protocol nu stabile"te o
cone,iune permanent! ntre cele dou! calculatoare.
4.2.3 Cu, e!"e ide#"i$ic'" u# c'*cu*'"&r ?# ree' %
Drice calculator gazd! conectat la )nternet este identificat n mod
unic de adresa sa IP 0)3 este acronimul de la "nternet rotocol1.
8ceasta reprezint! un num!r reprezentat pe 4= de bii, uzual sub
forma a 9 octei, cum ar fi de e,emplu: 094&116&106&140 "i este
numit! adresa B= numerica& Corespunz!toare unei adrese
numerice e,ist! "i o adres! B= simbolica* cum ar fi
http@//mail&md& 5e asemenea, fiecare calculator aflat ntrCo
reea local! are un nume unic ce poate fi folosit la identificarea
local! a acestuia.
<:
Clasa Java care reprezint! noiunea de adres! )3 este
BnetKddress&
4.2.4 Ce e!"e u# +&r" %
#n calculator are n general o singura leg!tur! fizic! la reea. Drice
informaie destinat! unei anumite ma"ini trebuie s! specifice
obligatoriu adresa )3 a acelei ma"ini. Fns! pe un calculator pot
e,ista concurent mai multe procese care au stabilite cone,iuni n
reea, a"tept%nd diverse informaii. 3rin urmare, datele trimise c!tre
o destinaie trebuie s! specifice pe l%ng! adresa )3 a calculatorului
"i procesul c!tre care se ndreapt! informaiile respective.
)dentificarea proceselor se realizeaz! prin intermdiul +&r"uri*&r&
#n port este un num!r de :< bii, care identific! n mod unic
procesele care ruleaz! pe o anumit! ma"in!. Drice aplicaie care
realizeaz! o cone,iune n reea va trebui s! ata"eze un num!r de
port acelei cone,iuni. -alorile pe care le poate lua un num!r de port
sunt cuprinse ntre A "i <>>4> 0deoarece sunt numere reprezentate
pe :< bii1, numerele cuprinse ntre A "i :A=4 fiind rezervate unor
servicii sistem "i, din acest motiv, nu trebuie folosite n aplicaii.
C*'!e de -'72 di# ;a<a4net
Clase din ?ava&net permit comunicare ntre procese folosind
protocoalele T)=@ XRV*XRV)onnection* SocYet*
ServerSocYet* "i XP=@ Patagram=acYet* PatagramSocYet*
JulticastSocYet4
4.2.5 4ucru* cu UR4)uri
Definiie
URL este acronimul pentru Uniform Resource Locator
"i reprezint! o referin! 0adres!1 la o resurs! aflat! pe
)nternet. 8ceasta este, n general, un fi"ier reprezent%nd o
pagin! &eb sau o imagine, ns! un #6+ poate referi "i
<=
interog!ri la baze de date, rezultate ale unor comenzi
0programe1, etc.
I,emple de #6+Curi sunt:
http@//?ava&sun&com* http@//mail&md&

Clasa care permite lucrul cu XRVCuri este ?ava4net4XRV& 8ceasta
are mai muli constructori pentru crearea de obiecte ce reprezint!
referine c!tre resurse aflate n reea, cel mai uzual fiind cel care
prime"te ca parametru un "ir de caractere. Fn cazul n care "irul nu
reprezint! un #6+ valid, va fi aruncat! o e,cepie de tipul
JalformedXRV<xception&
tr- {
XRV m-XRV ! ne" XRV(#http@//?ava&sun&com#);
} catch (JalformedXRV<xception e) {
& & &
}
Ddata creat, un obiect de tip #6+ poate fi folosit pentru
o aflarea informaiilor despre resursa referit! 0numele
calculatorului gazd!, numele fi"ierului, protocolul
folosit, etc1E
o citirea printrCun flu, a coninutului fi"ierului
respectiveE
o conectarea la acel #6+ pentru citirea "i scrierea de
informaii.
4.2.6 Ci"ire' c&#i#u"u*ui u#ui UR4
Drice obiect de tip #6+ poate returna un flu, de intrare de tip
)nputStream pentru citirea coninutului s!u. Secvena clasic! pentru
aceast! operaiune este:
<4
//Kfi(area paginii index&html de la adresa
"""&infoiasi&ro
public class )itireXRV {
public static void main(String./ args) thro"s
BE<xception{
OufferedReader br ! null;
tr- {
XRV resursa ! new
@R-(#http@//"""&infoiasi&ro#);
BnputStream An ! resursa4open3tream*+;
br ! ne" OufferedReader(ne"
BnputStreamReader(in));
String linie;
"hile ((linie ! br&readVine()) >! null) {
//proceseaza linia citita
S-stem&out&println(linie);
}
}catch(JalformedXRV<xception e) {
S-stem&err&println(#XRV incorect@ # , e);
}
finall- {
br&close();
}
}
}
Conectarea la un #6+ se realizeaz! prin metoda
open)onnection()&
4.2.7 6&cBe")uri
Definiie
#n soc#et (soclu) este o abstraciune soft'are folosit!
pentru a reprezenta fiecare din cele dou! JcapeteJ ale unei
cone,iuni ntre dou! procese ce ruleaz! ntrCo reea.
2iecare socBet este ata"at unui port astfel, nc%t s! poat!
identifica unic programul c!ruia i sunt destinate datele.
<9
SocBetCurile sunt de dou! tipuri:
o TC3, implementate de clasele SocYet "i
ServerSocYet E
o #53, implementate de clasa PatagramSocYet .
D aplicaie de reea ce folose"te socBetCuri se ncadreaz! n modelul
c*ie#"8!er1er de concepere a unei aplicaii. Fn acest model aplicaia
este format! din dou! categorii distincte de programe numite
servere, respectiv clieni. 3rogramele de tip server sunt cele care
ofer! diverse servicii eventualilor clieni, fiind n stare de a"teptare
at%ta vreme, c%t nici un client nu le solicit! serviciile 3rogramele de
tip client sunt cele care iniiaz! conversaia cu un server, solicit%nd
un anumit serviciu. #zual, un server trebuie s! fie capabil s! trateze
mai muli clieni simultan "i, din acest motiv, fiecare cerere
adresat! serverului va fi tratat! ntrCun fir de e,ecuie separat.
4.3 C&,u#ic're' +ri# c&#exiu#i
Fn acest model se stabile"te o cone,iune TC3 ntre un program
client "i un server, care furnizeaz! un anumit serviciu.
4.3.1 6"ruc"ur' >e#er'*2 ' u#ui !er1er -'7'" +e c&#exiu#i
"hile (true) {
accept a connection ;
create a thread to deal "ith the client ;
}// end "hile
I,emplu de program server:
import ?ava&net&D;
import ?ava&io&D;
public class SimpleServer extends Thread {
// Pefinesc portul pe care se g'se(te serverul
An afara intervalului 0C0215@
<>
public static final int %/RT 1 8100;
private static ServerSocYet serverSocYet !
null;
private SocYet clientSocYet ! null;
public void run() {
//<xecuta solicitarea clientului
String cerere* raspuns;
tr- {
//in este fluxul de intrare de la client
OufferedReader An ! ne"
OufferedReader(ne" BnputStreamReader(
client3oc?et4$et6nput3tream*+ ));
//out este flux de ie(ire c'tre client
=rintFriter out ! ne" =rintFriter(
client3oc?et4$et/utput3tream*+ );
//primesc cerere de la client
cerere ! in&readVine();
//trimit raspuns clientului
raspuns ! #hello # , cerere;
out&println(raspuns);
out&flush();
} catch (BE<xception e) {
S-stem&err&println(#<roare de
citire/scriere Rn# , e);
} finall- {
// Qnchid socYetul deschis pentru clientul curent
tr- {
clientSocYet&close();
} catch (BE<xception e) {
S-stem&err&println(#SocYetul nu poate fi
inchis Rn# , e);
}
}
}
public SimpleServer() thro"s BE<xception {
ser<er3oc?et 1 new 3er<er3oc?et*%/RT+;
<<
tr- {
//Ksteapta un client
client3oc?et 1 ser<er3oc?et4accept*+;
//<xecut solicitarea clientului AntrCun fir de
execuie
ne" Thread(this)&start();
} finall- {
serverSocYet&close();
}
}
public static void main(String./ args)
thro"s BE<xception {
SimpleServer server ! ne" SimpleServer();
}
}
4.3.2 6"ruc"ur' >e#er'*2 ' u#ui c*ie#" -'7'" +e c&#exiu#i
import ?ava&net&D;
import ?ava&io&D;
public class Simple)lient {
public static void main(String./ args) thro"s
BE<xception {
//adresa B= a serverului
String serverKddress ! #017&2&2&0#;
//portul la care serverul ofera serviciul
int =ERT ! 8022;
SocYet clientSocYet ! null;
=rintFriter out ! null;
OufferedReader An ! null;
String cerere* raspuns;
tr- {
client3oc?et 1 new 3oc?et*ser<er(ddress %/RT+;
out ! ne" =rintFriter(
clientSocYet&getEutputStream()* true);
in ! ne" OufferedReader(ne" BnputStreamReader(
<?
clientSocYet&getBnputStream()));
//se trimite o cerere la server
cerere ! #duYe#;
out&println(cerere);
//se asteapta raspuns de la server
raspuns ! in&readVine();
S-stem&out&println(raspuns);
} catch (XnYno"nUost<xception e) {
S-stem&err&println(#Serverul nu poate
fi gasit Rn# , e);
S-stem&exit(0);
} finall- {
if (out >! null)
out&close();
if (in >! null)
in&close();
if (clientSocYet>! null)
clientSocYet&close();
}
}
}
4.4 C&,u#ic're' +ri# d'"'>r',e
Fn acest model clientul trimite un pac$et cu cererea c!tre server,
acesta prime"te pac$etul "i returneaz! r!spunsul tot prin
intermediul unui pac$et. #n astfel de pac$et se numeste datagram
"i este reprezentat printrCun obiect din clasa Patagram=acYet.
3rimirea "i trimiterea datagramelor se realizeaz! tot prin
intermediul unui socBet, acesta fiind modelat printrCun obiect al
clasei PatagramSocYet.
4.4.1 6"ruc"ur' >e#er'*2 ' u#ui !er1er -'7'" +e d'"'>r',e
import ?ava&net&D;
import ?ava&io&D;
public class PatagramServer {
<@
public static final int =ERT ! 8122;
private PatagramSocYet socYet ! null;
Patagram=acYet cerere* raspuns ! null;
public PatagramServer() thro"s BE<xception {
3oc?et 1 new 0ata$ram3oc?et*%/RT+;
tr-
{
"hile (true) {
//Peclara pachetul An care va fi recepionat' cererea
b-te./ buf ! ne" b-te.136/;
cerere 1 new
0ata$ram%ac?et*bu" bu"4len$th+;
//K(tept' apariia unui pachet cu cererea
soc?et4recei<e*cerere+;
//Kfl' adresa (i portul de la care vine cererea
BnetKddress adresa ! cerere&getKddress();
int port ! cerere&get=ort();
//)onstruie(te r'spunsul
buf ! (#Uello # , ne"
String(cerere&getPata()))&getO-tes();
//Trimite un pachet cu r'spunsul c'tre client
raspuns 1 new 0ata$ram%ac?et*bu" bu"4len$th
adresa port+;
soc?et4send*raspuns+;
}
} finall- {
socYet&close();
}
}
public static void main(String./ args) thro"s
BE<xception {
ne" PatagramServer();
}
}
<;
4.4.2 6"ruc"ur' >e#er'*2 ' u#ui c*ie#" -'7'" +e d'"'>r',e
import ?ava&net&D;
import ?ava&io&D;
public class Patagram)lient {
public static void main(String./ args) thro"s
BE<xception {
//adresa B= (i portul la care ruleaz' serverul
BnetKddress address !
BnetKddress&getO-%ame(#017&2&2&0#);
int port!8122;
PatagramSocYet socYet ! null;
Patagram=acYet pacYet ! null;
b-te buf./;
tr- {
//)onstruie(te un socYet pentru comunicare
soc?et 1 new 0ata$ram3oc?et*+;
//)onstruie(te (i trimite pachetul cu cerere c'tre
server
buf ! #PuYe#&getO-tes();
pacYet ! ne" Patagram=acYet(buf*
buf&length* address* port);
socYet&send(pacYet);
//K(teapt' pachetul cu r'spunsul de la server
buf ! ne" b-te.136/;
pacYet ! ne" Patagram=acYet(buf*
buf&length);
socYet&receive(pacYet);
//Kfi(eaz' r'spunsul
S-stem&out&println(ne"
String(pac?et4$et0ata*+));
} finall- {
socYet&close();
}
}
?A
}
4.4.3 Tri,i"ere' de ,e!'Ce c2"re ,'i ,u*"i c*ie#i
5iverse situaii impun gruparea mai multor clieni astfel, nc%t un
mesaj 0pac$et1 trimis pe adresa grupului s! fie recepionat de
fiecare dintre ace"tia. Kruparea mai multor programe n vederea
trimiterii multiple de mesaje se realizeaz! prin intermediul unui
socBet special, descris de clasa JulticastSocYet, e,tensie a clasei
PatagramSocYet. #n grup de clieni abonai pentru trimitere
multipl! este specificat printrCo adres! )3 din intervalul 115&2&2&0
C 149&133&133&133 "i un port XP=. 8dresa 115&2&2&2 este
rezervat! "i nu trebuie folosit!.
4.4.4 D#re>i!"r're' u#ui c*ie#" ?#"r)u# >ru+
import ?ava&net&D;
import ?ava&io&D;
public class Julticast)lient {
public static void main(String./ args) thro"s
BE<xception {
//adresa B= (i portul care reprezint' grupul de
clieni
BnetKddress group !
BnetKddress&getO-%ame(#2A0404041#);
int port!BBBB;
JulticastSocYet socYet ! null;
b-te buf./;
tr- {
//Se al'tura grupului aflat la adresa (i portul
specificate
soc?et 1 new Culticast3oc?et*port+;
soc?et4;oin8roup*$roup+;
?:
//a(teapt' un pachet venit pe adresa grupului
buf ! ne" b-te.136/;
Patagram=acYet pacYet ! ne"
Patagram=acYet(buf* buf&length);
socYet&receive(pacYet);
S-stem&out&println(ne"
String(pacYet&getPata()));
} finall- {
soc?et4lea<e8roup*$roup+;
socYet&close();
}
}
}
4.4.5 Tr'#!,i"ere' u#ui ,e!'C c2"re u# >ru+
import ?ava&net&D;
import ?ava&io&D;
public class JulticastSend {
public static void main(String./ args) thro"s
<xception {
BnetKddress group !
BnetKddress&getO-%ame(#142&2&2&0#);
int port ! 5555;
b-te./ buf;
Patagram=acYet pacYet ! null;
//)reeaz' un socYet cu un numar oarecare
PatagramSocYet socYet ! ne" PatagramSocYet(2);
tr-{
//Trimite un pachet c'tre toi clienii din grup
buf ! (ne" String(#Salut grup#))&getO-tes();
pacYet ! ne" Patagram=acYet(buf* buf&length*
group* port);
socYet&send(pacYet);
?=
} finall- {
socYet&close();
}
}
}
4ucr're de *'-&r'"&r #r. 4
1. Te,' *ucr2rii5
)mplementarea aplicaiilor clientCserver multiCt$read
2. 6c&+u* *ucr2rii5
Fnsu"irea metodelor de utilizare a t$readCurilor n Java pentru
aplicaiile clientCserver
3. E"'+e*e de re'*i7're5
:1 #tilizarea clasei Thread pentru crearea unei clase noiE
=1 #tilizarea interfeei Runnable pentru crearea "i lansarea
de t$readCuriE
41 Crearea aplicaiei client H server pentru un singur
utilizatorE
91 Crearea aplicaiei client H server pentru un num!r fi,
de clieni, prin utilizarea t$readCurilorE
>1 #tilizarea interfeei grafice pentru appleturile multi
user.
4. Exe,+*u de re'*i7're5
:. Trebuie s! includ! clasa c*ie#"
=. Trebuie s! includ! clasa !er1er
4. Trebuie s! includ! clasa client H server pentru aplicaia
multiuser bazat! pe t$readuri
?4
Pr&>r', 1. A+*ic'ie c*ie#")!er1er5
Serverul trimie napoi te,tul trimis de care client.
import ?ava&io&D;
import ?ava&net&D;
public class client {
public static void main(String./ args) {
HH declaration section:
// client)lient@ our client socYet
// os@ output stream
// is@ input stream
SocYet clientSocYet ! null;
PataBnputStream is ! null;
=rintStream os ! null;
PataBnputStream inputVine !null;
// Bnitialization section@
// Tr- to open a socYet on port 1111
// Tr- to open input and output streams

tr- {
clientSocYet ! ne" SocYet(#localhost#* 1111);
os ! ne"
=rintStream(clientSocYet&getEutputStream());
is ! ne"
PataBnputStream(clientSocYet&getBnputStream());
inputVine ! ne" PataBnputStream(ne"
OufferedBnputStream(S-stem&in));
} catch (XnYno"nUost<xception e) {
S-stem&err&println(#PonZt Yno" about
host#);
} catch (BE<xception e) {
S-stem&err&println(#)ouldnZt get B/E
for the connection to host#);
}
?9
// Bf ever-thing has been initialized then "e "ant
to "rite some data
// to the socYet "e have opened a connection to on
port 1111
if (clientSocYet >! null [[ os >! null [[
is >! null) {
tr- {
// Yeep on reading from/to the socYet till "e
receive the #EY# from the server*
// once "e received that then "e "ant to breaY&
String responseVine;
os&println(inputVine&readVine());
"hile ((responseVine !
is&readVine()) >! null) {

S-stem&out&println(responseVine);
if
(responseVine&indexEf(#EY#) >! C0) {
breaY;
}
os&println(inputVine&readVine());
}
// clean up@
// close the output stream
// close the input stream
// close the socYet
os&close();
is&close();
clientSocYet&close();
} catch (XnYno"nUost<xception e) {
S-stem&err&println(#Tr-ing to
connect to unYno"n host@ # , e);
} catch (BE<xception e) {
S-stem&err&println(#BE<xception@ #
, e);
}
?>
}
}
}
import java.io.7E
import ?ava&net&D;
public class server {
public static void main(String args./) {
// declaration section@
// declare a server socYet and a client socYet for
the server
// declare an input and an output stream
ServerSocYet echoServer ! null;
String line;
PataBnputStream is;
=rintStream os;
SocYet clientSocYet ! null;

// Tr- to open a server socYet on port 1111
// %ote that "e canZt choose a port less than 0214
if "e are not
// privileged users (root)
tr- {
echoServer ! ne" ServerSocYet(1111);
}
catch (BE<xception e) {
S-stem&out&println(e);
}
// )reate a socYet ob?ect from the ServerSocYet to
listen and accept
// connections&
// Epen input and output streams
tr- {
clientSocYet ! echoServer&accept();
?<
is ! ne"
PataBnputStream(clientSocYet&getBnputStream());
os ! ne"
=rintStream(clientSocYet&getEutputStream());
// Ks long as "e receive data* echo that data bacY
to the client&
"hile (true) {
line ! is&readVine();
os&println(#;rom server@ #, line);
}
}
catch (BE<xception e) {
S-stem&out&println(e);
}
}
}
Pr&>r', 2. A+*ic'ie c*ie#")!er1er ,u*"iu!er5
Serverul deserve"te mai muli clieni ce particip! la discuie.
HHClientMM.java
import ?ava&io&D;
import ?ava&net&D;
import ?ava&a"t&D;
import ?ava&a"t&event&D;
class Bnterface extends ;rame{
Pialog form ! null;
TextKrea "ndMmsg ! null*"ndMnames!null;
Outton bMsend ! null;
Text;ield toMsend ! null;
Bnterface(String "indo"Mname){
super("indo"Mname);
set;ont(ne" ;ont(#)omic#*;ont&OEVP*01));
setOacYground()olor&green);
"ndMmsg ! ne"
TextKrea(##*05*32*TextKrea&S)REVVOKRSMT<RTB)KVME%VN
);
"ndMmsg&set<ditable(false);
??
"ndMnames ! ne"
TextKrea(##*05*02*TextKrea&S)REVVOKRSMT<RTB)KVME%VN
);
"ndMnames&set<ditable(false);
toMsend ! ne" Text;ield(32);
bMsend ! ne" Outton(#Send#);
=anel forMsends ! ne" =anel();
=anel forM"nds ! ne" =anel();
forMsends&add(toMsend);
forMsends&add(bMsend);
forM"nds&add("ndMnames);
forM"nds&add("ndMmsg);
add(forMsends*OorderVa-out&SEXTU);
add(forM"nds*OorderVa-out&)<%T<R);
setSize(322*452);
setTisible(true);
}
}
class ;orm extends Pialog implements
KctionVistener{
public Text;ield forMhost!null*forMname!null;
public Outton begin ! null;
public String./ host ! null;
public String./ name ! null;
Vabel lMhost ! ne" Vabel(#Uost@ #);
Vabel lMname ! ne" Vabel(#%ame@#);
;orm(Bnterface chat*String./ host*String./ name){
super(chat * #Regestration@#*true);
set;ont(ne" ;ont(#)omic#*;ont&OEVP*01));
this&host ! host;
this&name ! name;
forMhost ! ne" Text;ield(02);
forMname ! ne" Text;ield(02);
=anel forMtexts ! ne" =anel();
forMtexts&add(lMhost);
forMtexts&add(forMhost);
forMtexts&add(lMname);
forMtexts&add(forMname);
begin ! ne" Outton(#Oegin#);
begin&addKctionVistener(this);
=anel forMbutton ! ne" =anel();
?@
forMbutton&add(begin);
add(forMtexts*OorderVa-out&)<%T<R);
add(forMbutton*OorderVa-out&SEXTU);
setOacYground()olor&green);
setSize(082*003);
setTisible(true);
}
public void action=erformed(Kction<vent ae){
host.2/ ! forMhost&getText();
name.2/ ! forMname&getText();
dispose();
}
}
class Read implements KctionVistener{
// Transmiterea mesa?ului
Bnterface "nd;
String name!#not @#;
SocYet ss;
=rintFriter out ! null;
String fromXser!##;
Read(SocYet s*Bnterface "){
"nd!";
ss!s;
tr-{
out ! ne" =rintFriter(ss&getEutputStream()*
true);
}catch(BE<xception io){}
}
public void action=erformed(Kction<vent ae){
fromXser!"nd&toMsend&getText();
"nd&toMsend&setText(##);
out&println(name,fromXser);
fromXser!##;
}
public void set%ame(String name){
this&name!name,# @ #;
}
}
public class )lientJJ{
public static void main(String./ args) thro"s
BE<xception {
?;
String./ name ! ne" String.0/ * host ! ne"
String.0/;
Bnterface "nd ! ne" Bnterface(#)hat#);
ne" ;orm("nd*host*name);
Read reader ! null;
SocYet YYSocYet ! null;
OufferedReader in ! null;
tr- {
YYSocYet ! ne" SocYet(host.2/* 8888);
in ! ne" OufferedReader(ne"
BnputStreamReader(YYSocYet&getBnputStream()));
} catch (XnYno"nUost<xception e) {
S-stem&err&println(#PonZt Yno" about
host&#);
S-stem&exit(0);
} catch (BE<xception e) {
S-stem&err&println(#)ouldnZt get B/E
for the connection&#);
S-stem&exit(0);
}
String fromServer;
reader!ne" Read(YYSocYet*"nd);
reader&set%ame(name.2/);
"nd&setTitle(name.2/);
final =rintFriter out ! reader&out;
// mesa?e de sistem
out&println(#\#,name.2/);
"nd&addFindo"Vistener(ne" Findo"Kdapter(){
public void "indo")losing(Findo"<vent "e){
out&println(#1001444#);
S-stem&exit(2);
}
});
"nd&bMsend&addKctionVistener(reader);
"nd&toMsend&addKctionVistener(reader);
"hile(((fromServer ! in&readVine()) >!
null) [[ (reader>!null)) {
if((fromServer&charKt(2)!!Z\Z) [[
(fromServer&charKt(0)!!ZIZ)){
"nd&"ndMnames&setText(##);
continue;
@A
}
if(fromServer&charKt(2)!!Z\Z){

"nd&"ndMnames&append(fromServer&substring(0),ZRnZ);
}else
"nd&"ndMmsg&append(fromServer,#Rn#);
}
in&close();
YYSocYet&close();
}
}
//ServerJJ&?ava
import ?ava&net&D;
import ?ava&io&D;
public class ServerJJ {
public static void main(String./ args) thro"s
BE<xception {
SocYet./ m-socYs!ne" SocYet.02/;
String./ names ! ne" String.02/;
SocYet tempMsocY ! null;
int count!2;
for(int i!2;i+02;i,,){
m-socYs.i/ ! null;
names.i/ ! null;
}
ServerSocYet serverSocYet ! null;
boolean listening ! true;
tr- {
serverSocYet ! ne" ServerSocYet(8888);
} catch (BE<xception e) {
S-stem&err&println(#)ould not listen on
port@ 8888&#);
S-stem&exit(C0);
}
"hile (listening){
if(count+02
[[((tempMsocY!serverSocYet&accept())>!null)){
for(int i!2;i+02;i,,){
@:
if(m-socYs.i/!!null){
count!i;
m-socYs.i/!tempMsocY;
tempMsocY!null;
ne"
ServerThread(m-socYs.count/*m-socYs*count*names)&st
art();
breaY;
}
}
count!2;
for(int i!2;i+02;i,,)
if(m-socYs.i/>!null) count,,;
S-stem&out&println(count);
}else S-stem&out&println(#Server is full#);
}
serverSocYet&close();
}
}
class ServerThread extends Thread{
String names./ ! null;
String name ! null;
public int o"nMnum;
private SocYet socYet ! null;
private SocYet./ m-s!null;
=rintFriter outKll ! null;
public ServerThread(SocYet socYet*SocYet./
m-*int num*String names./) {
super(#ServerThread#);
this&socYet ! socYet;
this&m-s ! m-;
o"nMnum ! num;
this&names ! names;
}
public void run() {
tr- {
=rintFriter out ! ne"
=rintFriter(socYet&getEutputStream()* true);
OufferedReader in ! ne" OufferedReader(
@=
ne" BnputStreamReader(
socYet&getBnputStream()));
String inputVine* outputVine;
"hile ((inputVine ! in&readVine())>! null) {
if (inputVine&e]ualsBgnore)ase(#1001444#))
{ for(int i ! 2;i+02;i,,){
if(names.i/ >! null)
if(name&compareTo(names.i/)!!2){
names.i/ ! null;
breaY;
}
}
for(int i!2;i+02;i,,){
if(m-s.i/>!null){
outKll ! ne"
=rintFriter(m-s.i/&getEutputStream()* true);
outKll&println(#\I#);
for(int ?!2;?+02;?,,){
if(names.?/ >! null)

outKll&println(names.?/);
}
outKll ! null;
}
}
breaY;
}
if(inputVine&charKt(2)!!Z\Z){
for(int i ! 2;i + 02; i,,){
if(names.i/ !! null){
name ! inputVine;
names.i/ ! inputVine;
breaY;
}
}
for(int i!2;i+02;i,,){
if(m-s.i/>!null){
outKll ! ne"
=rintFriter(m-s.i/&getEutputStream()* true);
@4
outKll&println(#\I#);
for(int ?!2;?+02;?,,){
if(names.?/ >! null)

outKll&println(names.?/);
}
outKll ! null;
}
}
}else
for(int i!2;i+02;i,,){
if(m-s.i/>!null){
outKll ! ne"
=rintFriter(m-s.i/&getEutputStream()* true);
outKll&println(inputVine);
outKll ! null;
}
}
}
socYet&close();
m-s.o"nMnum/!null;
out&close();
in&close();
} catch (BE<xception e) {
e&printStacYTrace();
}
}

}
5. Pr&-*e,e +r&+u!e5
14 Se cere elaborarea unei perec$i de programe clientCserver cu
urm!toarea funcionalitate:
C serverul creeaz! la prima conectare a unui client un
fi"ier te,t vid cu numele acestuia 0clientului1E
C clientul poate trimite serverului unul sau mai multe
fi"iere "i cere interclasarea acestora cu fi"ierul careCi
@9
poart! numeleE rezultatul interclas!rii va fi reinut n
fi"ierul cu numele clientuluiE
C clientul poate cere serverului returnarea coninutului
fi"ierului ceCi poart! numele.
DQS. Se cere scrierea unui server concurent folosind t$readCuri.
)nterclasarea fi"ierelor se va face folosind t$readCuri.

2. Se cere elaborarea unei perec$i de programe clientCserver cu
urm!toarea funcionalitate:
C serverul calculeaz! e,presii aritmetice primite de la
clieni "i p!streaz! rezultatul fiec!rei e,ecuii n c%te un
fi"ier te,t cu numele clientului.
C clientul poate trimite dou! sau mai multe e,presii
aritmetice 0n forma polonez! postfi,at!Hprefi,at!1
pentru a fi evaluate, poate cere rezultatele tuturor
e,ecuiilor anterioare, sau al unei e,ecuii anume.
DQS. Se cere scrierea unui server concurent folosind t$readCuri.
Ivaluarea e,presiilor "i scrierea rezultatului n fi"ierul te,t se va
face folosind t$readCuri. Se cere sincronizarea accesului la fi"ierul
cu rezultate.

3. Se cere elaborarea unei perec$i de programe clientCserver cu
urm!toarea funcionalitate:
C serverul gestioneaz! o list! de fi"iere.
C clienii pot cere lista fi"ierelor disponibile, pot trimite
noi fi"iere, respectiv pot cere returnarea coninutului
unui anumit fi"ier C ordonat alfabetic pe linii.
DQS. Se cere scrierea unui server concurent folosind t$readCuri.
8ccesul la lista de fi"iere va fi sincronizat. Drdonarea fi"ierelor te,t
se va face folosind t$readCuri 0se cere ca fi"ierele te,t s! aib!
dimensiunea de minim >AA Pb1.
@>
4. Se cere elaborarea unei perec$i de programe clientCserver cu
urm!toarea funcionalitate:
C serverul gestioneaz! o list! de fi"iere.
C clienii pot cere lista fi"ierelor disponibile, pot trimite
noi fi"iere, respectiv pot cere returnarea rezultatului
interclas!rii a dou! sau mai multe fi"iere.
DQS. Se cere scrierea unui server concurent folosind t$readCuri.
8ccesul la lista de fi"iere va fi sincronizat. )nteclasarea fi"ierelor
te,t se va face folosind t$readCuri0se cere ca fi"ierele te,t s! aib!
dimensiunea de minim >AA Pb1.

5. Se cere elaborarea unei perec$i de programe clientCserver cu
urm!toarea funcionalitate:
C serverul ntreine un fi"ier te,t cu triplete de forma
0produsCpreCtimpul n care produsul e disponibil pentru
licitaie1.
C clienii pot cere lista produselor, respectiv pot licita
pentru un produs.
C serverul face updateCul n fi"ierul de produse 0la
e,pirarea timpului1 "i notific! clienii interesai de
rezultatul licitaiei.
DQS. Se cere scrierea unui server concurent folosind t$readCuri.
8ccesul la lista de produse va fi sincronizat.

6. Se cere elaborarea unei perec$i de programe clientCserver cu
urm!toarea funcionalitate:
C serverul simuleaz! un g$i"eu de banc! la care se pot
face e,trageri de numerar, respectiv aliment!ri de cont.
C clienii se autentific! pe baza unui num!r de cont "i a
unei parole "i pe l%ng! cele dou! operaii menionate
0e,tragereHalimentare1 pot cere "i un istoric al
tranzaciilor 0listarea tuturor tranzaciilor, nsumarea
tuturor depunerilorHe,tragerilor1.
@<
DQS. Se cere scrierea unui server concurent folosind t$readCuri.
8ccesul la lista de clieni "i la istoricul tranzaciilor va fi
sincronizat. Fnsumarea depunerilorHe,tragerilor se va face folosind
t$readCuriHprocese.
7. Se cere elaborarea unei perec$i de programe clientCserver cu
urm!toarea funcionalitate:
C serverul reine ntrCo structur! de directoare proprii
0pentru fiecare client un director1 imagini n diferite
formate 0gifHjpgHetc...1E
C clientul poate acorda drepturi r' pentru directorul
propriu "i altor clieni.
C clientul poate cere ad!ugarea, "tergerea uneiHunor
imagini nHdin directorul propriu 0respectiv directoarele
pentru care are drepturi corespunzatoare1.
DQS. Se cere scrierea unui server concurent folosind t$readCuri.
8ccesul la lista de drepturi "i la directoarele clienilor va fi
sincronizat. 8d!ugareaH"tergerea imaginilor se va face folosind
t$readCuri.
8. Se cere elaborarea unei perec$i de programe clientCserver cu
urm!toarea funcionalitate:
C serverul simuleaz! un server de mail: stoc$eaz!
mesajele pentru clieni, respectiv trimite mesaje pentru
ali clieni.
C un client poate vizualizaH"terge mesajele
primiteHtrimise "i poate trimite mesaje c!tre ali
utilizatori.
DQS. Se cere scrierea unui server concurent folosind t$readCuri.
-izualizareaH"tergereaHtrimiterea de mesaje se va face folosind
t$readCurie.

@?
9. Se cere elaborarea unei perec$i de programe clientCserver cu
urm!toarea funcionalitate:
C serverul simuleaz! o bibliotec! electronic! n sensul
c! pune la dispoziia clienilor c!ri 0fi"iere te,t1.
C clienii pot consulta lista de c!ri din bibliotec!,
respectiv pot JmprumutaJ o carte 0serverul mut!
fi"ierul la client1 pentru o perioad! pe care o specific!.
5up! e,pirarea timpului de mprumut clientul
Jreturneaz!J cartea bibliotecii 0mut! fi"ierul napoi la
server1.
C serverul verific! dup! fiecare transfer JintegritateaJ
c!rii 0folosind sume de control, semn!turi digitale,
etc.1, iar n cazul n care o carte nu e disponibil! pune
doritorul n a"teptare p%n! la returnarea c!rii.
DQS. Se cere scrierea unui server concurent folosind t$readCuri.
8ccesul la lista c!rilor va fi sincronizat.
TFmprumuturileTHTreturnareaTHverificarea Tintegrit!iiT se va face
folosind t$readCuri.

10. Se cere elaborarea unei perec$i de programe clientCserver cu
urm!toarea funcionalitate:
C serverul simuleaz! un operator telefonic 0reine
pentru fiecare client un nume "i un num!r de telefon1E
C la intervale aleatoare clienii JvorbescJ la telefon
0trimit spre server o perec$e de numere reprezent%nd
num!rul de impulsuri asociat convorbirii "i num!rul cu
care sCa vorbit1E
C la sf%r"it de lun! serverul trimite fiec!rui client nota
de plat! 0nr. de impulsuri7valoare impuls1, "i poate
furniza la cerere un istoric al convorbirilor pentru
ultimele , luni.
DQS. Se cere scrierea unui server concurent folosind t$readCuri.
8ccesul la lista de clieni "i la istoricul convorbirilor va fi
@@
sincronizat. Calculul notei de plat! pentru fiecare client se va face
folosind t$readCuri.
:I:4IO3RAFIE
:. 5oug +ea, SConcurrent rogramming n $ava % Design
principles and atternsT8ddisonC&esley :;;<.
=. QruceIcBel, free eCbooB ST&in#ing n $ava T, ST&in#ing n
'nterprise $ava T, """&Oruce<cYel&com
4. Cay S. Norstman, Karz Cornell, SCore $ava
T(
)Tv. :, 1. 2., Sun
Microsystems 3ress, =AA=.
@;

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