Documente Academic
Documente Profesional
Documente Cultură
Interfeegrafice
Firedeexecuie
Construireaistartareafirelordeexecuie
Terminareafirelordeexecuie
Prioritateafirelordeexecuie
Metodajoin()
Sincronizareafirelordeexecuie
Blocurisincronizate
Interblocaje(deadlocks)
Sincronizareafirelorutilizndmetodelewait(),notify()sinotifyAll()
Firedeexecuie
Demulteoriestenevoiecaoaplicaiespoatsrealizezesimultanmaimulteactiviti(de
exemplu o aplicaie de tip server va trebui s fie capabil s deserveasc simultan mai muli
clieni). Firele de execuie reprezint mecanismul prin care pot fi implementate n cadrul unui
programsecvenedecodceseexecutvirtualnparalel.
Figura1.Firedeexecuie
Trebuie fcut distincie ntre fire de execuie i procese. Dei ambele concepte implic
execuia n paralel a unor secvene de cod exist o serie de deosebiri fundamentale ntre
proceseifiredeexecuie.Proceselesuntentitiindependenteceseexecutindependenti
sunt gestionate de ctre nucleul sistemului de operare. Firele de execuie sunt secvene ale
unuiprogram(proces)ceseexecutaparentnparalelncadrulunuisingurproces.
Strileunuifirdeexecuie
Unfirdeexecuiesepoateaflainunadintreurmtoarele4stri:
1.Newobiectulfirdeexecuieafostcreatdarncanuafoststartat.
2. Runnable Firul se afla in starea in care poate fi rulat in momentul in care procesorul
devinedisponibil.
3. Dead Calea normala prin care un fir se termina este prin ieirea din metoda run(). Se
poateforaterminareafiruluiapelndmetodastop()darnuserecomandafolosireasa,fiind
ometodadeprecatedinJava2.
4. Blocked Firul de execuie este blocat si nu poate fi rulat, chiar daca procesorul este
disponibil.
http://control.aut.utcluj.ro/isp/lab9/firedeexecutie.htm
1/12
11/20/2015
Interfeegrafice
Figura2.Strileunuifirdeexecuie
Construireaistartareafirelordeexecuie
DupcumsetiepunctuldestartaluneiaplicaiiJavaestefunciamain.nmomentullansrii
n execuie a aplicaiei aceasta va conine un fir de execuie ce va executa aceast funcie
main.Aadaroaplicaiejavaconinecelpuinunfirdeexecuie.
PentruaconstruiunfirdeexecuietrebuieextinsclasaThreadisuprascrismetodarun()din
cadrul acestea. n cadrul metodei run() se va implementa secvena de instruciuni ce se va
executanmomentulncareunfirdeexecuieestestartat.
Pentrualansanexecuieunfirsefolosetemetodastart()(motenitdeasemeneadincadrul
clasei Thread). Aceast metod este responsabil cu iniializarea tuturor mecanismelor
necesarepentruaputeaexecutaunfirdeexecuie,dupcarevaapelaautomatmetodarun().
packageisp.fire
publicclassCounterextendsThread{
Counter(Stringname){
super(name)
}
publicvoidrun(){
for(inti=0i<20i++){
System.out.println(getName()+"i="+i)
try{
Thread.sleep((int)(Math.random()*1000))
}catch(InterruptedExceptione){
e.printStackTrace()
}
http://control.aut.utcluj.ro/isp/lab9/firedeexecutie.htm
2/12
11/20/2015
Interfeegrafice
}
System.out.println(getName()+"jobfinalised.")
}
publicstaticvoidmain(String[]args){
Counterc1=newCounter("counter1")
Counterc2=newCounter("counter2")
Counterc3=newCounter("counter3")
c1.start()
c2.start()
c3.start()
}
}
OBSERVATIE:metodarun()nutrebuieapelatainmodexplicitdectreprogramatorpentruc
aceasta va fi apelat n mod automat atunci cnd firul de execuie este lansat n execuie
folosindmetodastart().
OBSERVATIE:unfirdeexecuieodatastartatnuvamaiputeafistartatncaodata.Dacase
ncearcapelareametodeistart()pentruunfirdejapornit,sevageneraoeroare.
EXERCIIU:Verificaifuncionareaaplicaieianterioare.nlocuiincadrulaplicaieianterioare
apelulmetodelorstart()dincadrulfuncieimain()cuapelulmetodelorrun().Verificaidinnoui
observaidiferenanfuncionareaprogramului.
Limbajul java nu permite motenire multipl. Aceasta nseamn ca dac avem o clas care
motenete deja o clas, i dorim s o transformm n fir de execuie nu vom putea folosi
metoda prezentat anterior de extindere a clasei Thread. Pentru a putea rezolva astfel de
situaii java pune la dispoziie o a doua metod de construire a firelor de execuie folosind
interfaaRunnable.
ncontinuaresevaprezentaaplicaiaanterioarmodificatpentruafolosiinterfaarunnablen
scopulconstruiriifirelordeexecuie.
packageisp.fire
publicclassCounterRunnableimplementsRunnable{
publicvoidrun(){
Threadt=Thread.currentThread()
for(inti=0i<20i++){
System.out.println(t.getName()+"i="+i)
try{
Thread.sleep((int)(Math.random()*1000))
}catch(InterruptedExceptione){
e.printStackTrace()
}
}
System.out.println(t.getName()+"jobfinalised.")
}
publicstaticvoidmain(String[]args){
CounterRunnablec1=newCounterRunnable()
http://control.aut.utcluj.ro/isp/lab9/firedeexecutie.htm
3/12
11/20/2015
Interfeegrafice
CounterRunnablec2=newCounterRunnable()
CounterRunnablec3=newCounterRunnable()
Threadt1=newThread(c1,"conuter1")
Threadt2=newThread(c2,"conuter2")
Threadt3=newThread(c3,"conuter3")
t1.start()
t2.start()
t3.start()
}
}
Terminareafirelordeexecuie
Odeosebitaatenietrebuiedatamoduluiincareunfirdeexecuiesetermina.ncadrulclasei
Threadexistdefinitmetodastop()cepoatefifolositpentruterminareaunuifir,dar,nueste
recomandat,dealtfel,aceastametodaestedeprecated(numaiesterecomandatdectre
Sunpentruafiutilizat).Calearecomandatadeterminareaunuifiresteprinrevenireanormala
( return ) din run(). Aadar in cadrul metodei run se recomand adugarea unor blocuri
condiinalecaresdetermineterminareafiruluideexecuie,respectivieireadinmetodarun.
Acestmecanismnuesteutildefiecaredatadeoareceinmomentulincareunfiresteblocat(
datorita unor instruciuni wai(), sleep(), join(), operatii I/O ), acesta nu poate verifica nici o
condiie. Pentru a termina un fir care este blocat se utilizeaz metoda interrup(). Aceasta
metodadeterminaaruncareauneiexcepiiInterruptedExceptioncaretrebuieprinsa.
Prioritateafirelordeexecuie
Prioritateaunuifirdeexecuiespuneplanificatoruluideexecuieafirelorcatdeimportanteste
acesta, i ce prioritate trebuie s i se acorde pentru executarea instruciunilor sale. Aceasta
insemncdacmaimultefiredeexecuiesuntblocateinateptareaexecuiei,planificatorull
vaalegeprimadatapecelcuprioritatemaimare.Aceastanunseamncafirelecuprioritate
maimicanuvoraveaalocattimpdinprocesor.
Pentru a seta prioritatea unui fir se utilizeaz metoda setPriority(), iar pentru obinerea
prioritii unui fir se utilizeaz metoda getPriority() (metodele fac parte din clasa Thread) .
FirelepotprimiprioritiintrevalorileMIN_PRIORITYsiMAX_PRIORITY(constantedefinitenclasa
Thread).
packageisp.fire.prioritate
importjava.awt.*
importjavax.swing.*
publicclassMainFrameextendsJFrame{
publicMainFrame(){
setTitle("Threadprioritytest.")
setDefaultCloseOperation(EXIT_ON_CLOSE)
http://control.aut.utcluj.ro/isp/lab9/firedeexecutie.htm
4/12
11/20/2015
Interfeegrafice
setLayout(newGridLayout(5,1))
setSize(300,300)setVisible(true)
}
publicvoidaddNewThreadComponent(CounterXx){
JPanelp=newJPanel()
p.setLayout(newFlowLayout())
p.add(newJLabel(x.getName()))
p.add(x.getProgressBar())
add(p)
}
publicstaticvoidmain(String[]args){
MainFramemf=newMainFrame()
CounterXc1=newCounterX(1000,1)
mf.addNewThreadComponent(c1)
CounterXc2=newCounterX(1000,5)
mf.addNewThreadComponent(c2)
CounterXc3=newCounterX(1000,10)
mf.addNewThreadComponent(c3)
c1.start()
c2.start()
c3.start()
}
}
classCounterXextendsThread{
intsize
JProgressBarpBar
CounterX(ints,intpriority){
this.size=s
pBar=newJProgressBar(0,size)
pBar.setStringPainted(true)
this.setPriority(priority)
JComponentgetProgressBar(){returnpBar}
publicvoidrun(){
for(inti=0i<=sizei++){
try{Thread.sleep(1)
}catch(InterruptedExceptione){
e.printStackTrace()
}
pBar.setValue(i)
}
}
}
EXERCIIU:Modificaiprogramuldemaisuspentruapermitesetareanumeluifiecruifirde
execuie.
http://control.aut.utcluj.ro/isp/lab9/firedeexecutie.htm
5/12
11/20/2015
Interfeegrafice
OBSERVAIE:Programatorulnutrebuiesasebazezepeprioritiinconstruireaprogramului,
ntructacestapoatedarezultatediferitepesistemediferite.
Metodajoin()
Metodajoin()aparineclaseiThreadsiesteutilizatapentruadeterminaunfirdeexecuies
atepteterminareaunuialtfirdeexecuie.
packageisp.fire.sincronizare
classJoinTestextendsThread
{
Stringn
Threadt
JoinTest(Stringn,Threadt){this.n=nthis.t=t}
publicvoidrun()
{
System.out.println("Firul"+n+"aintratinmetodarun()")
try
{
if(t!=null)t.join()
System.out.println("Firul"+n+"executaoperatie.")
Thread.sleep(3000)
System.out.println("Firul"+n+"aterminatoperatia.")
}
catch(Exceptione){e.printStackTrace()}
publicstaticvoidmain(String[]args)
{
JoinTestw1=newJoinTest("Proces1",null)
JoinTestw2=newJoinTest("Proces2",w1)
w1.start()
w2.start()
}
}
Sincronizareafirelordeexecuie
Blocurisincronizate
Unuldintreaspectelecelemaiimportantedecaretrebuieinutcontatuncicndselucreazcu
firedeexecuieestemodulincareacesteaacceseazresurselecomune.Astfelinmomentulin
care doua sau mai multe fire mpart o resursa comuna acestea trebuie sa i sincronizeze
accesullaacearesursa.
Unexempludeastfeldesituaieestecelalfirelorconsumator\producator.Unfirintroducedate
http://control.aut.utcluj.ro/isp/lab9/firedeexecutie.htm
6/12
11/20/2015
Interfeegrafice
Prevenireacoliziuniiinjavasefaceutilizndmetodelesincronizatesaublocurilesincronizate.
Ometodaestesincronizataatuncicndareinfatacuvntulcheiesynchronized.
synchronizedvoidf(){/*...*/}
synchronizedvoidg(){/*...*/}
Unblocsincronizatestedefinitsubforma:
synchronized(obiect){...}
Numai un singur fir poate accesa la un moment dat o metoda sincronizata a unui obiect.
Fiecare obiect are inclus (automat) un monitor sau un zvor. In momentul in care o metoda
sincronizataaunuiobiectesteapelata,monitorulesteachiziionatdectrefirulcareaaccesat
metoda.Attatimpcatmetodasincronizataesteinexecuienicioaltametodasincronizatanu
vamaiputeafiapelatadectreunaltfir.
OBSERVAIE:Inmomentulincareunfirncearcsaaccesezeometodasincronizataaunui
obiect care are monitorul acaparat de ctre un alt fir, acesta se blocheaz in ateptarea
eliberriimonitorului.
packageisp.fire.sincronizare
publicclassTestSincronizare{
publicstaticvoidmain(String[]args){
Punctp=newPunct()
FirSetfs1=newFirSet(p)
FirGetfg1=newFirGet(p)
fs1.start()
fg1.start()
}
}
classFirGetextendsThread{
Punctp
publicFirGet(Punctp){
this.p=p
}
publicvoidrun(){
inti=0
inta,b
while(++i<15){
//synchronized(p){
a=p.getX()
try{
sleep(50)
}catch(InterruptedExceptione){
e.printStackTrace()
}
http://control.aut.utcluj.ro/isp/lab9/firedeexecutie.htm
7/12
11/20/2015
Interfeegrafice
b=p.getY()
//}
System.out.println("Amcitit:["+a+","+b+"]")
}
}
}//.class
classFirSetextendsThread{
Punctp
publicFirSet(Punctp){
this.p=p
}
publicvoidrun(){
inti=0
while(++i<15){
inta=(int)Math.round(10*Math.random()+10)
intb=(int)Math.round(10*Math.random()+10)
//synchronized(p){
p.setXY(a,b)
//}
try{
sleep(10)
}catch(InterruptedExceptione){
e.printStackTrace()
}
System.out.println("Amscris:["+a+","+b+"]")
}
}
}//.class
classPunct{
intx,y
publicvoidsetXY(inta,intb){
x=ay=b
}
publicintgetX(){returnx}
publicintgetY(){returny}
}
Exerciiu: Testai programul anterior. Decomentai blocurile sincronizate din cadrul claselor
FirGetiFirSetiobservaidiferenanfuncionare.
Interblocaje(deadlocks)
Folosirea blocurilor sincronizatea n mod greit poate duce la situaii de interblocaje (eng.
deadlock) ntre firele de execuie. Astfel de situaii apar atunci cnd dou fire sunt blocate,
fiecareateptndunuldupcellalteliberareaunuimonitor.
Aplicaiaurmtoareexemplificapariiasituaieideinterblocajntredoufirecefolosescblocuri
sincronizate.
http://control.aut.utcluj.ro/isp/lab9/firedeexecutie.htm
8/12
11/20/2015
Interfeegrafice
packageisp.fire.sincronizare
publicclassDeadlock{
publicstaticvoidmain(String[]args){
finalRobotalphonse=newRobot("Alphonse")
finalRobotgaston=newRobot("Gaston")
newThread(newRunnable(){
publicvoidrun(){alphonse.proceseazaPiesa(gaston)}
}).start()
newThread(newRunnable(){
publicvoidrun(){gaston.proceseazaPiesa(alphonse)}
}).start()
}
}
classRobot{
privatefinalStringname
Piesapiesa
publicRobot(Stringname){
this.name=name
this.piesa=newPiesa()
}
publicStringgetName(){
returnthis.name
}
publicsynchronizedvoidproceseazaPiesa(Robotr){
System.out.println(name+"proceseazapiesa")
piesa.procesare()
r.primestePiesa(this)
}
publicsynchronizedvoidprimestePiesa(Robotr){
System.out.println(r.getName()+"atransmispiesacatre"+name)
this.piesa=r.getPiesa()
}
privatePiesagetPiesa(){
returnpiesa
}
}
classPiesa{
publicvoidprocesare(){
System.out.println("Piesaseproceseaza")
try{
Thread.sleep(100)
}catch(InterruptedExceptione){
e.printStackTrace()
}
}
}
Sincronizareafirelorutilizndmetodelewait(),notify()sinotifyAll()
Metodele wait() si notify() sunt utilizate pentru a bloca i debloca firele de execuie. Aceste
dou metode fac parte din clasa Object. Motivul acestei poziionri este c acestea
http://control.aut.utcluj.ro/isp/lab9/firedeexecutie.htm
9/12
11/20/2015
Interfeegrafice
manipuleazmonitoareleobiectelor,si,larndullor,monitoarelesegsesclaniveluloricrui
obiect.
Metodelewaitsinotifypotfiapelatedoardininteriorulunorblocurisaumetodesincronizate.
Ceea ce nseamn ca aceste metode, pentru un obiect data, pot fi apelate doar de ctre
deintorulmonitoruluiobiectului.
In momentul in care un fir este blocat prin apelarea metodei wait() monitorul deinut de
respectivulfiresteeliberat.
OBSERVAIE:Nuutilizaimetodelestop()sisuspend()deoarecefolosireaacestoraincadrul
unorblocurisincronizateduceladeadlokntructmonitorulnuesteeliberat.
publicclassTest{
publicstaticvoidmain(String[]args){
Bufferb=newBuffer()
Producerpro=newProducer(b)
Consumerc=newConsumer(b)
Consumerc2=newConsumer(b)
//Lanseazacele3firedeexecutie.Seobservacacele3firede
executie
//folosescincomunobiectulbdetipBuffer.Existaunfirproceeste
//responsabilcuadaugareadeelementeinbuffersidouaobiecte
//responsabilecuextragereaelementelordinbuffer.
pro.start()
c.start()
c2.start()
}
}
/**
*Aceastaesteoclasadetipfirdeexecutie.Incadruluneibucleinfinitesunt
*generatenumeredetipdoublesisuntadaugateincadrulunuiobiectdetip
Buffer
*apelandmetodaput.Aduagareelementelorsefacelaintervalede1secunda.
*
*/
classProducerimplementsRunnable
{
privateBufferbf
privateThreadthread
Producer(Bufferbf){this.bf=bf}
publicvoidstart()
{
if(thread==null)
{
thread=newThread(this)
thread.start()
}
}
http://control.aut.utcluj.ro/isp/lab9/firedeexecutie.htm
10/12
11/20/2015
Interfeegrafice
publicvoidrun()
{
while(true)
{
bf.put(Math.random())
System.out.println("Amscris.")
try
{Thread.sleep(1000)}catch(Exceptione){}
}
}
}
/**
*Aceastaesteoclasadetipfirdeexecutie.Introbuclainfinitasuntcitite
elemente
*dincadrulunuiobiectdetipBuffer.
*/
classConsumerextendsThread
{
privateBufferbf
Consumer(Bufferbf){this.bf=bf}
publicvoidrun()
{
while(true)
{
System.out.println("Amcitit:"+this+">>"+bf.get())
}
}
}
classBuffer
{
/*
*VectorfolositpentruainmagazinaobiectedetipDouble.
*/
ArrayListcontent
/**
*Prinintermediulacesteimetodesuntadaugateelementeincontainerul
content.
*Seobservacaaceastametodaestesincronizata.Metodafafiapelatade
firele
*deexecutiedetipProducer.
*
*Dupaadaugareaunuielementincontainerseapeleazametodanotify()
aceastaasigura
*trezireaunuifirdeexecutieceafostblocatprinapelulfunctieiwait().
*@paramd
*/
synchronizedvoidput(doubled)
{
content.add(newDouble(d))
notify()
}
http://control.aut.utcluj.ro/isp/lab9/firedeexecutie.htm
11/12
11/20/2015
Interfeegrafice
/**
*Aceastametodaestefolositapentruaextrageelementedincadrul
containerului
*content.Seobservacaaceastametodaestesincronizata.
*Dacacontainerulestegolseapeleazametodawait().Aceastavabloca
firul
*deexecutieapelantpanainmomentulincareunfirdeexecutieproducator
*vaadaugaincontainerunelementsivaapelametodanotify()(vezimetoda
put(...))
*
*@return
*/
synchronizeddoubleget()
{
doubled=1
try
{
if(content.size()==0)wait()
d=(((Double)content.get(0))).doubleValue()
content.remove(0)
}catch(Exceptione){e.printStackTrace()}
returnd
}
}
Exerciiu:Testaiaplicaiademaisus.nmomentulrulriisevaobservaapariiauneierori.
Corectaieroaresitestaidinnouaplicaia.
Pentruaplicatiigraficeclickaici
http://control.aut.utcluj.ro/isp/lab9/firedeexecutie.htm
12/12