Sunteți pe pagina 1din 12

11/20/2015

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.

Clasa java ce implementeaz mecanismele necesare pentru a iniializa i executa un fir de


execuieesteclasaThread.

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

intrunbuffer,iarceldealdoileacitetedatelepusedeprimulfirinbuffer. Evident cele doua


firenutrebuiesaaccesezesimultanbufferulsitrebuiesaaibunaccessincronizatlaacesta.

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:Metodawait(milis) poate fi utilizata in locul metodei Thread.sleep(milis), avantajul


fiind ca firul poate fi deblocat nainte de expirarea timpului de ateptare (ceea ce in cazul
sleep()nuesteposibil).

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

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