ȘiruriJAVA
Ș IRURI Ș I OPERAȚII CU Ș IRURI
Prezentare generală
• Crearea obiectelor de tip ș ir
• Metode de subș iruri
• Operatorul de concatenare
• Ș irurile sunt imuabile
• Alte metode ale clasei String
• Exemplu folosind metodele de ș iruri
CREAREAOBIECTELORSTRING
Ș irurile sunt Obiecte
• Un ș ir este o succesiune de caractere închise între ghilimele. De exemplu: "Bună"
• Prelucrarea stringurilor este una dintre cele mai importante ș i frecvente aplicaț ii ale unui computer
• Java recunoaș te acest fapt ș i, prin urmare, oferă suport special pentru ș iruri pentru a facilita utilizarea acestora.
convenabil
• Fiecare ș ir este o instanț ă a funcț iei încorporate JavaȘ irclasă, astfel, String-urile sunt obiecte.
Declaraț ie
• Ca orice obiect, un ș ir poate fi creat folosindnouaș a cum este în exemplul următor:
String str1 = new String(„Bună dragă”);
• Cu toate acestea, ca un suport suplimentar, Java permite crearea obiectelor String fără utilizarea lui new, ca în:
Cum eș ti?
• Aceasta este inconsistentă cu modul în care Java tratează celelalte clase.
SUBSTRINGS
• Obiectele String sunt reprezentate ca o secvenț ă de caractere indexate de la 0.
Example:String greeting = “Hello,World”;
Bună, W o r ld !
0 1 2 3 4 5 6 7 8 9 10 11 12
• O operaț ie comună pe ș iruri este extragerea unei subș ir dintr-un ș ir dat.
• Java oferă două metode pentru această operaț iune:
subsir(jos); Returnează subș irul de la început până la
sfârș itul ș irului
Returnează
substring(început, sfârș it); un subș ir de la început la sfârș it
dar fără a include caracterul de la sfârș it.
Exemple:
String sub = [Link](0, 4); Iad
String w = [Link](7, 12); lume
String tail = [Link](7); lume!
OPERATOR DE CONCATENARE
• O altă operaț iune comună asupra unui String este concatenarea.
• Ca o altă susț inere specială pentru String, Java a supraincarcat operatorul + pentru a fi utilizat pentru a concatena două
Obiecte de tip string pentru a obț ine unul mai mare.
String firstName= “Amr”;
String lastName= “Al-Ibrahim”;
String numeComplet = numeFamilie + " " + prenume;
Al-Ibrahim Amr
• Dacă unul dintre operanzii operatorului + este un ș ir, celălalt este automat convertit în ș ir ș i
cele două ș iruri sunt apoi concatenat.
String course = “ICS”;
int cod = 102;
String courseCode = curs+cod ICS102
• We frequently use the concatenation operator inprintlnstatements.
[Link]("Aria ="+aria);
• Trebuiesă[Link],cecrezicăvaafiș aurmătoareainstrucț iune?
[Link]("Sum ="+5+6);
Ș IRURILESUNTIMUTABILE
• O altă caracteristică specială a stringurilor este că acestea sunt imutabile. Adică, odată ce un obiect string este
creat, conț inutul său nu poate fi modificat. De exemplu, luaț i în considerare următoarele:
String str1 = “Hello World”;
str1 = [Link](4);
• În loc să se schimbe obiectul str1, un alt obiect este creat. Primul este colectat ca ș i gunoi,
astfel, referinț a la cel dinainte este pierdută.
• Faptul că sirurile sunt imuabile permite sistemului Java să proceseze siruri foarte eficient.
• De exemplu, ia în considerare următoarele:
String str1 = “Hello”;
String str2 = "Salut";
• Ne-am aș tepta la următoarele
• Dar de fapt, acesta este ceea ce se întâmplă
• Sistemul Java este suficient de inteligent pentru a ș ti că cele două ș iruri sunt identice ș i alocă acelaș i
locaț ia de memorie pentru cele două obiecte
METODELECLASEISTRING
• În plus faț ă de metodele de subș ir, sunt furnizate mai multe metode predefinite în
clasa String încorporată. Unele dintre acestea sunt:
lungimeInt() returnează numărul de caractere din acest ș ir
StringtoUpperCase() returnează un nou String, echivalent cu majusculele/minusculele acestui String
StringtoLowerCase()
booleanequals(s) returnează adevărat dacă este acelaș i cu acest String.
boolean equalsIgnoreCase(s)
intcompareTo(String s) returnează un număr pozitiv, 0 sau un număr negativ dacă acest String este mai mare, egal sau mai mic
mulț umesc.
intcomparaCuIgnoraCase(s)
charAt(index) returnează caracterul din acest String, la poziț ia index.
intindexOf(ch) Returnează indexul primei / ultimei apariț ii a cuvântului "chin" în acest ș ir. Dacă nu este găsit, returnează -1.
intultimulIndexDe(ch) întors
Stringtrim() returnează un String, obț inut prin îndepărtarea spaț iilor de la începutul ș i sfârș itul acestui string.
static String valueOf(any primitiv Returnează o reprezentare String a argumentului
tip)
Stringconcat(s) echivalent cu simbolul +
EXEMPLUUTILIZÂNDMETODELECLASEISTRING
• Următorul program generează o parolă pentru un student folosind iniț ialele ș i vârsta sa.
public class MakePassword {
public static void main(String[] args) {
String firstName = "Amr";
String middleName = "Samir";
String lastName = "Ibrahim";
//extrage iniț ialele
String initials =
[Link](0,1)+
[Link](0,1)+
[Link](0,1);
//adaugă vârsta
int varsta = 20;
String parola = [Link]() + varsta;
[Link]("Parola ta =" + parola);
}
}
CLASASTRINGBUFFER
• O secvenț ă de caractere modificabilă, sigură pentru fire. Un buffer de ș iruri este asemănător unui String, dar poate fi modificat.
În orice moment, conț ine o anumită secvenț ă de caractere, dar lungimea ș i
conț inutul secvenț ei poate fi schimbat prin anumite apeluri de metode.
• Buffer-urile de ș iruri sunt sigure pentru utilizarea de către mai multe fire. Operaț iile principale asupra unui StringBuffer sunt
metodele append ș i insert. Fiecare ajută la convertirea unui anumit datum într-un ș ir ș i apoi
ataș ează sau inserează caracterele acelui ș ir în buffer-ul de ș iruri. Metoda append întotdeauna
adaugă aceș ti caractere la sfârș itul tamponului; metoda de inserare adaugă caracterele la un
punct specificat.
• De exemplu, dacă z se referă la un obiect de tip buffer de ș iruri al cărui conț inut curent este "start", atunci
apelul metodei [Link]("le") ar provoca ca bufferul de string să conț ină "startle", în timp ce [Link](4,
"le") ar schimba bufferul de ș ir pentru a conț ine "starlet".
• În general, dacă sb se referă la o instanț ă a unui StringBuffer, atunci [Link](x) are acelaș i efect ca ș i
[Link]([Link](), x).
CONSTRUCTORISTRINGBUFFER
Constructor ș i Descriere
StringBufferConstruieș te un buffer de ș iruri fără caractere în el ș i cu o capacitate iniț ială
de 16 caractere.
StringBuffer(Secvenț ă de caractereseq)Construieste un buffer de stringuri care contine acelasi
caractere ca secvenț a de caractere specificată.
StringBuffer(int capacitate) Construieste un buffer de stringuri fără caractere în el ș i
capacitate iniț ială specificată.
StringBuffer(Ș irConstruieste un tampon de stringuri iniț ializat cu conț inutul
ș ir specificat.
import [Link].*;
clasă GFG {
public static void main(String[] args)
{
StringBuffer s = new StringBuffer("Salut lume");
[Link](5, 8,"oo");
[Link](s);
}
}
CLASASTRINGBUILDER
• Obiectele StringBuilder sunt asemănătoare cu obiectele String, cu excepț ia că pot fi modificate. Prin urmare, Java
Clasa StringBuilder este, de asemenea, utilizată pentru a crea obiecte de tip string mutable (modificabile). StringBuilder este la fel
ca StringBuffer, cu o diferenț ă importantă. StringBuilder nu este sincronizat, ceea ce
înseamnă că nu este sigur pentru fire. În orice moment, lungimea ș i conț inutul secvenț ei pot fi schimbate
prin invocarea metodelor.
Constructorii clasei StringBuilder:
• StringBuilder ( ) : Construieș te un constructor de ș iruri fără caractere în el ș i cu o capacitate iniț ială de 16
caractere.
• StringBuilder ( int capacitate ) : Construieste un constructor de stringuri fara caractere in el si o capacitate initiala
capacitatea specificată de argumentul capacitate.
• StringBuilder ( String str ) : Construieste un builder de string-uri initializat cu continutul specificat
Capacitatea iniț ială a constructorului de ș iruri este 16 plus lungimea argumentului ș ir.
Methods of StringBuilder class
• append() : Metoda append() concatenează argumentul dat (reprezentare sub formă de string) la
sfârș itul obiectului StringBuilder invocat. Clasa StringBuilder are mai multe metode append() suprasolicitate
metodă. Câteva sunt:
– StringBuilder append(String str)
– StringBuilder adaugă(int n)
– StringBuilder adaugă(Object obj)
CLASASTRINGBUILDER
• insert()-Metoda insert() inserează argumentul dat (reprezentarea sub formă de ș ir) în apelant.
Obiect StringBuilder la poziț ia dată.
• metoda replace() înlocuieș te ș irul de la indexul de început specificat până la indexul de sfârș it.
• reverse()-Această metodă inversează caracterele dintr-un obiect StringBuilder.
• delete()-Metoda delete() a clasei StringBuilder ș terge ș irul de la indexul de început specificat până la
endIndex.
• capacity()-Metoda capacity() returnează capacitatea actuală a obiectului StringBuilder. Capacitatea este
cantitatea de stocare disponibilă pentru caracterele nou introduse, dincolo de care va avea loc o alocare.
Nu. StringBuffer StringBuilder
1) StringBuffer este sincronizat, adică este sigur pentru fir. Aceasta înseamnă că două
StringBuilder nu este-
firele nu pot apela metodele StringBuffer simultan. sincronizat, adică nu este sigur pentru fire.
Asta înseamnă că două fire pot apela
methods of StringBuilder
simultan.
2) StringBuffer este mai pu ț in eficient decât StringBuilder. StringBuilder este mai mult
mai eficient decât StringBuffer.
THREADEJAVA
CONTENTS
[Link] este un fir?
[Link] ț i ș i lansa ț i un fir
3. Ciclu de via ț ă al unui fir
[Link] un fir
[Link] firului
6. alte probleme
CE ESTE UN FIR?
• Un program secvenț ial (sau pe un singur fir) este acela care, atunci când este executat, are doar un singur flux de control.
– de exemplu, în orice moment, există maximum o singură instruc ț iune (sau afirma ț ie sau punct de execu ț ie) care este în curs de
executat în program.
• Un program multi-threaded este unul care poate avea mai multe fluxuri de control atunci când este executat.
– La un moment dat, pot exista multiple instruc ț iuni sau puncte de execu ț ie care sunt executate în
program
Într-un browser web, putem face următoarele sarcini în acela ș i timp:
-1. derula ț i o pagină,
-2. descarcă un applet sau o imagine,
-3. redă sunetul,
-4 tipăre ș te o pagină.
• Un fir este un flux secvenț ial unic de control într-un program.
PROGRAMEÎNUNFIRDEXECUȚIEVSPROGRAMEMULTIFIREDEXECUȚIE
{ A();
newThreads {
A(); A1(); A2(); A3(); { A1(); A2(); A3() };
B1(); B2(); } {B1(); B2() }
}
}
ECOLOGIAFIRELORÎNtr-unPROGRAMJAVA
început de java din main(String[])
început de firul principal
început de firul B
durata de viață a firului C
[Link]
THREAD
• Fiecare fir de execuț ie Java este încapsulat într-o instanț ă [Link].
• Două moduri de a defini un fir:
1. Extinde clasa Thread
2. Implementează interfaț a Runnable :
package [Link];
interfaț ă publică Runnable { public void run(); }
• Pa ș ii pentru extinderea clasei Thread:
1. Subclasa ț i clasa Thread;
2. Suprascrie ț i metoda defaultThread run(), care este punctul de intrare al firului, ca metoda main(String[]).
într-un program Java.
DEFINEȚIUNFIRE
// Exemplu:
public class Print2Console extinde Thread {
public void run() { // run() este pentru un fir de execuț ie ceea ce este main() pentru un program java
pentru (int b = -128; b < 128; b++) [Link](b); }
… // metode, câmpuri suplimentare …
}
• Implementează interfaț a Runnable dacă ai nevoie de o clasă părinte:
prin extinderea JTextArea putem reutiliza tot codul existent al JTextArea
clasa publică Print2GUI extinde JTextArea implementează Runnable {
public void run() {
pentru (int b = -128; b < 128; b++) adaugă( [Link](b) + "\n" ); }
}
CUMSĂLANSEZIUNFIR
1. crea ț i o instan ț ă a [ unei subclase a ] ofThread, să spunem thread.
[Link] thread = new Print2Console();
[Link] thread = newThread( new Print2GUI( .. ) );
2. apelati metoda sa start(), [Link]();. // observatie: nu apelati run() !!
Ex:
– Printer2Console t1 = new Print2Console(); // t1 este o instan ț ă de fir de execu ț ie!
-[Link](); // acesta va începe un nou fir, care î ș i va începe execu ț ia apelând
[Link]()
– ... // firul părinte continuă imediat aici fără a a ș tepta copilul
fir pentru a-ș i finaliza execuț ia. cf: [Link]();
-Print2GUI jtext = new Print2GUI();
– Thread t2 = newThread( jtext);
-[Link]();
– …
[Link]
// Constructori publici
• Thread([ThreadGroup grup,] [Runnable ț intă,]
[ String name ] );
–Instances :
–Fthread();
–Thread(Runnable target);
–Thread(Runnable ț intă, String nume);
-Thread(String nume);
-Fir(ThreadGroup grup, Runnable ț intă);
–Thread(ThreadGroup grup, Runnable ț intă, String nume);
–Thread(ThreadGroup grup, String nume);
numele este un ș ir folosit pentru a identifica instan ț a firului
// grupul este grupul de fire la care apar ț ine acest fir.
M E T O D E D E ACCES LA PROPRIETĂȚ I S O M E T H R E A D
• int getID() // fiecare fir are un ID unic, începând cu jdk1.5
• String getName(); setName(String)
– // ob ț ine/setează numele firului
• getThreadGroup();
• int getPriority(); setPriority(int) // firul are prioritate în [0, 31]
• [Link] getState() // returnează starea curentă a acestui fir
• booleanisAlive()
– Verifică dacă acest fir a fost început ș i nu a murit încă.
• booleanisDaemon()
Testează dacă acest fir de execu ț ie este un fir daemon.
• booleanisInterrupted()
– Testează dacă acest fir a fost întrerupt.
METODESTATEPECAREACESSEACURRENT
• staticFirthread-ul curent()
Returnează o referin ț ă la obiectul firului de execu ț ie care este în prezent în execu ț ie.
• static booleanholdsLock(Obiectobj)
Returnează adevărat dacă ș i numai dacă firul de execu ț ie curent de ț ine blocarea monitorului asupra obiectului specificat.
• static booleaninterupt()
Verifică dacă firul curent a fost întrerupt.
• static voidsomn( [ milis lungi [, int nanosecunde ]] )
Cauzează firul de execu ț ie curent să doarmă (să înceteze execu ț ia) pentru timpul specificat.
• static voidrandament()
Cauzează obiectul firului de execu ț ie curent să se oprească temporar ș i să permită altor fire să se execute.
UNEXEMPLE
public class SimpleThread extinde Thread {
public SimpleThread(String str) { super(str); }
public void run() {
pentru (int i = 0; i < 10; i++) {
[Link](i + " " + getName());
încercă { // în acest moment, firul curent este 'acesta'. }
[Link]((long)([Link]() * 1000));
} catch (InterruptedException e) {}
}
DONE!
} }
PROGRAMPRINCIPAL
public classDouăFireTest {
public static void main (String[] args) {
new SimpleThread("Thread1").start();
new SimpleThread("Thread2").start(); } }
possible output:
0 Fir1 5 Fir1 DONE! Thread2
0 Fir2 5 Fir2 9 Fir1
1 Fir2 6 Fire2 FINALIZAT! Thread1
1 Thread1 6 Fire1
2 Fir1 7 Fir1
2 Fir2 7 Fire2
3 Fir2 8 Fir2
3 Fir1 9 Fir2
4 Fir1 8 Fir1
4 Fir2
[Link]ȚĂALUNUIFIRJAVA
Nou (Executabil blocat/aș teptând ) * Executabil mort(terminat)
• sleep(long ms [,int ns])
• // dormi (ms + ns x 10–3)milisecunde ș i apoi continuă
• [ IO ] blocat de metoda/blocul sincronizat
-synchronized( obj ) { … } // declara ț ie sincronizată
– sincronizat m(… ) { … } // metodă sincronizată
– // întoarce la executable dacă IO este complet
• obj.aș teaptă()
• // revenire la rulabil prin [Link]() sau [Link]()
• alătură-te(long ms [,int ns])
• //Aș teaptă cel mult ms milisecunde plus ns nanosecunde pentru ca acest fir să moară.
3 . STATELE ( CICLUL DE VIAȚ Ă ) AL UNUI THREAT ( JAVA 1 . 5 )
public class Thread { .. // enum în 1.5 este o clasă specială pentru tipuri finite.
public static enum State { //[Link] for referring to this nested class
NOI,// după newThread(), dar înainte de start().
EXECUTABIL, // după start(), când rulează sau este pregătit
BLocat, // blocat de blocarea monitorului
// blocked by a synchronized method/block
A Ș TEPTARE, // a ș teptând să fiu notificat; fără limită de timp setată
// aș teptaț i(), uniț i-vă()
TIMED_WAITING, // aș teptând să fiu notificat; timpul de aș teptare setat
// sleep(time), wait(time), join(time)
TERMINTAT // executare completă sau după stop()
}…
}
The life cycle of a Java thread
executabil
ia cheia blocat/în așteptare
start() rezumat()
fiu nou(…)
nu funcționează firul t se termină
(gata) somn terminat
[Link](), [Link]()
interrompe()
(bit set) interupe()
yield(), sau
preemptiv programat
de către OS (aruncă excepție)
de OS
o.așteaptă()
dormi(…)
alergare [Link]()
stop()
terminat suspend()
run() iese
blocat de lacăt
normal sau
anormal
METODEDETRANSIȚIEASTATELORPENTRUÎNFRUNTARE
• public synchronized native void start() {
Notă: Când apelăm
– începe un fir apelând metoda sa run() ...
[Link](), noi în fapt folosim
Este ilegal să ini ț iezi un fir de mai multe ori. timpul firului curent pentru
• public final void join( [long ms [, int ns]]); executa codul firului t
– Lasă firul curent să a ș tepte ca firul receptor să moară pentru cel mult ms+ns timp
• static void yield() // apelabil doar de firul curent
Cauzează obiectul firului de execu ț ie curent să se oprească temporar ș i permite altora
fire de executat.
• public final void relua(); // depreciat
• public final void suspend();// învechit poate duce la blocaj
• public final void stop(); // deprecat duce la inconsistenț ă
// verificarea stării
• public boolean esteViu() ; // adevărat dacă este runnable sau blocat
4.ÎNTRERUPEREAFIRELOR
• O apelare blocantă/în aș teptare (sleep(), wait() sau join()) la un fir t poate fi terminată printr-un
InterruptedException aruncat prin invocarea [Link]().
– aceasta oferă o modalitate alternativă de a părăsi starea de blocare.
– cu toate acestea, fluxul de control este diferit de cazul normal.
Ex: public void run() {
încearcă { … în timp ce (mai este de lucru){ // Ieșirea normală din sleep() continuă aici
fă ceva muncă;
sleep( … ); // dă o ș ansă unei alte fire să lucreze
}
}
catch (InterruptedException e) { //dacă ai fost trezit de interrupt() atunci continuă aici
… // firul întrerupt în timpul somnului sau a ș teptării }
}
• Notă: metoda interrupt() nu va arunca o InterruptedException dacă firul nu este
blocat/aș teptând. În acest caz, firul trebuie să apeleze metoda statică interrupted() pentru a afla
dacă a fost recent întrerupt. Aș a că ar trebui să rescriem bucla while prin
în timp ce ( ! întrerupt() && mai_mult_de_făcut() ) { … }
METODERELATELAÎNTERUPERE
• interrupț ie void
– trimite o cerere de întrerupere unui fir.
statusul „ interupt” al firului este setat pe adevărat.
– dacă firul este blocat de sleep(), wait() sau join(), statusul întrerupt al firului este
cură ț at ș i o InterruptedException este aruncată.
– concluzie: rulabil ==> bitul „ interupt” setat, dar nicio Excep ț ie aruncată.
– neexectabil ==> Excepț ia a fost declanș ată, dar bitul „interzis” nu este setat
• static boolean întrerupt() // interogare distrugătoare
– Verifică dacă firul curent (self) a fost întrerupt.
resetare a stării "interupt" la fals.
• boolean esteInterrupt() // interogare non-distructivă
– Testează dacă acest fir a fost întrerupt fără a schimba starea „ interupt”.
– poate fi folosit pentru a interoga firul de execu ț ie curent sau un alt fir de execu ț ie care nu este activ. de exemplu.
dacă ([Link]()|[Link]()...) ...
5. SINCRONIZAREA THREADA
• Problemă cu orice program Java multithreaded :
Două sau mai multe obiecte Thread accesează aceleaș i date.
• prea puț in sau fără sincronizare ==> există inconsistenț ă, pierdere sau
corupț ia datelor.
• prea multă sincronizare ==> blocaj sau sistem îngheț at.
• Între acestea există un proces inechitabil în care mai multe fire pot
înfometează-o pe cealaltă care înghite toate resursele între ele.
MULTITHREADING POT CAUZA INCONSISTENȚE : UN EXEMPLU
Două depozite concomitente de 50 într-un cont cu o balanț ă iniț ială de 0.
void depune(int suma) {
int x = [Link]();
x += amount;
[Link](x); }
• depunere(50) : // depunere 1
depozit(50) : // depozit 2
x = [Link]() //1
x += 50; //2 x = [Link]() //4
[Link](x) //3 x += 50;//5
Secvenț a de execuț ie: [Link]ăSold(x)//6
1,4,2,5,3,6 will result in unwanted result !!
Soldul final este 50 în loc de 100!!
METODEȘIAFERENTESINCRONIZATE
• multithreading poate duce la pericole de cursă, unde ordini diferite de
intercalarea produce rezultate diferite ale calculului.
–Ordinea intercalării este în general imprevizibilă ș i nu este determinată de
programatorul.
• Metoda sincronizată Java (precum ș i declaraț ia sincronizată) poate preveni
corpul său fiind intercalat prin metode relevante.
-synchronized( obj ) { … } // declaraț ie sincronizată cu obj ca blocaj
–sincronizat … m(… ) {… } //metodă sincronizată cu this ca lacăt
Când un fir execută (corpul) unui bloc sincronizat
metodă/declaratie, toate celelalte fire sunt excluse de la executarea oricărei
metodă sincronizată cu acelaș i obiect ca ș i blocare.
SINCRONIZAREATHREDELOR
• Java foloseș te conceptul de monitor pentru a realiza excluderea mutuală ș i sincronizarea
între fire.
• Metodele/declaraț iile sincronizate garantează excluderea reciprocă.
Excluderea reciprocă poate împiedica un fir de execuț ie să-ș i finalizeze sarcina. Aș a că
monitorul permite unui fir să aș tepte până la o schimbare de stare ș i apoi să-ș i continue munca.
• wait(), notify() ș i notifyAll() controlează sincronizarea firelor.
–Permite unui fir să aș tepte o condiț ie (stare logică) ș i altuia să o seteze ș i
apoi notifică firele de aș teptare.
– variabile de condi ț ie => variabile booleene de instan ț ă
– wait => wait();
– notifying => notify(); notifyAll();
UTILIZARETIPICĂ
void sincronizat doWhenCondition() {
în timp ce ( !condiț ie )
aș teaptă(); // aș teaptă până când cineva ne anunț ă despre schimbările în condiț ie
... // fă ceea ce trebuie făcut când condiț ia este adevărată
}
synchronized void changeCondition {
// schimbă unele valori folosite în testul de condiț ie
notifică(); // Informează firele de aș teptare că ceva s-a schimbat
}
Note:A method may serve both roles; it may need some condition to occur to do something and its
acț iunea mea cauzează schimbarea condiț iei.
PROBLEMAPRODUCĂTORULUI/CUMPARATORULUI
• Două fire: producător ș i consumator, un monitor: CubbyHole
• Producătorul :
–generează o pereche de întregi între 0 ș i 9 (inclusiv), o stochează într-un CubbyHole
obiect ș i imprimă suma fiecărui pereche generată.
– dorme pentru o perioadă aleatorie de timp între 0 ș i 100 de milisecunde înainte de
repetarea ciclului de generare a numerelor:
• Consumatorul
–consumă toate perechile de numere întregi din CubbyHole cât mai repede posibil.
disponibil.
[Link]
public class Producer extinde Thread {
private CubbyHole cubbyhole; int id privat;
public Producer(CubbyHole c, int id) {
cubbyhole = c; [Link] = id; }
public void run() {
pentru (int i = 0; i < 10; i++)
pentru(int j =0; j < 10; j++ ) {
[Link](i, j);
[Link]("Producătorul #" + [Link] + " a pus: (" + i + "," + j + ").");
încearcă { doarme((int)([Link]() * 100)); }
prinde (InterruptedException e) { }
};
}
}
[Link]
public class Consumator extinde Thread {
private CubbyHole cubbyhole;
private int id;
public Consumer(CubbyHole c, int id) {
cubbyhole = c; [Link] = id; }
public void run() {
int valoare = 0;
pentru (int i = 0; i < 10; i++) {
value = [Link]();
[Link]("Consumator #" + [Link]
+ " got: " + value);
} } }
CUBBYHOLEFĂRĂÎNMUTARE
EXCLUDERE
public class CubbyHole { private int x,y;
public synchronized int get() { return x+y; }
public synchronized void pune(int i, int j) {x = i; y = j } }
Problemă: inconsistenț a datelor pentru unele secvenț e de execuț ie posibile
– Presupunem că după put(1,9) datele sunt corecte, adică, (x,y) = (1,9)
– And then two method calls get() and put(2,0) try to access CubbyHole concurrently => possible inconsistent
result:
-(1,9) get() { return x + y; } { return 1 + y ; }
-(1,9) puneti(2,0) {x = 2; y = 0;} (x,y) = (2,0)
– (2,0) get() { return 1 + y ;} întoarce 1 + 0 = întoarce 1 (în loc de 10!)
• Prin marcarea metodelor get() ș i put() ca fiind sincronizate, rezultatul inconsistent nu poate
se întâmplă deoarece, prin definiț ie, când oricare metodă este în execuț ie de un fir, nu
other thread can execute any synchronized method with this CubbyHole object as
lacăt.
CULCUȘUL
CUBBYHOLEFĂRĂSINCRONIZARE
public class CubbyHole {
private int x,y;
public synchronized int get() { return x+y; }
public synchronized void punte(int i, int j) { x = i; y = j; }
}
Probleme:
1. Consumatorul mai rapid decât Producătorul: unele date au fost primite de mai multe ori.
2. producător mai rapid decât consumator: unii pun date neutilizate de consumator.
ex: Producătorul #1 a pus: (0,4)
Consumer #1 got: 3
Consumatorul #1 a primit: 4
Producătorul #1 a pus: (0,4)
Consumator #1 a primit: 4 Producătorul #1 a pus: (0,5)
Producătorul #1 a pus: (0,5) Consumer #1 got: 5
OALTĂIMPLEMENTARECUBICĂ(ÎNCĂINCORCTĂ!)
pubic class CubbyHole { int x,y; boolean available = false;
public synchronized int get() { // nu va funcț iona!
dacă (disponibil == adevărat) {
disponibil = fals; returnează x+y;
} } // eroare de compilare!! trebuie să returneze o valoare în orice caz!!
public synchronized void put(int a, int b) { // nu va functiona!
dacă (disponibil == fals) {
available = true; x=a;y=b;
} }} // but how about the case that availeable == true ?
• pune(..); ia(); ia(); // 2ndget() trebuie să returneze ceva!
• put(..);put(..); // 2ș iput() nu are efect!
[Link]
public class CubbyHole {
privat int x,y; private boolean disponibil = false; // variabila condiț ie
public synchronized int get() {
în timp ce (disponibil == fals) {
încearcă { [Link](); } catch (InterruptedException e) { } }
available = false; // enforce consumers to wait again.
notifyAll(); // notifică toț i producătorii/consumatorii să concureze pentru execuț ie!
// foloseș te notify() dacă doreș ti doar să trezeș ti un singur fir de execuț ie aș teptând!
return x+y; }
public synchronized void pune(int a, int b) {
în timp ce (disponibil == adevărat) {
încearcă { aș teaptă(); } prinde (InterruptedException e) { } }
x= a; y = b;
available = true; // wake up waiting consumer/producer to continue
notifyAll(); // or notify(); }}
CLASAPRINCIPALĂ
clasa publică ProducerConsumerTest {
public static void main(String[] args) {
CubbyHole c = new CubbyHole();
Producător p1 = nou Producător(c, 1);
Consumator c1 = nou Consumator(c, 1);
[Link]();
c1 începe();
} }
OTHERISSUES
• Priorităț ile firului
– public final int getPrioritate();
– public final void setPriority();
– obț ine/setează prioritatea între MIN_PRIORITY ș i MAX_PRIORITY
– prioritate implicită : PRIORITATE_NORMALĂ
• Fire daemon:
-isDaemon(), setDaemon(boolean)
Un fir Daemon este unul care există pentru a deservi alte fire.
JVM-ul se închide dacă toate firele din el sunt fire Daemon.
– setDaemon(.) trebuie apelat înainte ca firul să fie început.
• public static boolean detineBlocare(Object obj)
– verifică dacă acest fir de execu ț ie de ț ine blocarea pe obj.
– ex: synchronized( e ){[Link](e) ? true:false // is true… }
THREADGROUPS
• Fiecare fir Java este un membru al unui grup de fire.
• Grupurile de thread-uri oferă un mecanism pentru a colecta multiple thread-uri într-un singur obiect ș i
manipulând acele fire toate deodată, mai degrabă decât individual.
• Când creezi un fir,
– lasă sistemul de execu ț ie să pună noul fir de execu ț ie într-un grup implicit rezonabil (grupul de fir curent)
sau
– setaț i explicit grupul noului fir.
• nu poț i muta un fir într-un grup nou după ce firul a fost creat.
– atunci când este lansat, firul principal al programului apar ț ine grupului principal de fire.
CREAREAUNUIFIREXPLICITÎNTR-OGRUPĂ
publicThread(ThreadGroup grup, Runnable runnable)
publicThread(ThreadGroup grup, String nume)
publicThread(ThreadGroup group, Runnable runnable, String name)
ThreadGroup myThreadGroup = newThreadGroup(
"Grupul meu de firuri"
Thread myThread = newThread(myThreadGroup,
"o discuț ie pentru grupul meu"
• Obț inerea grupului unei fire
theGroup = [Link]();
CLASATHREADGROUP
Metode de gestionare a colecț iilor:
clasa publică EnumerateTest {
public void listaThread-urileCurente() {
ThreadGroup grupCurent =
[Link]().getThreadGroup();
int numThreads = [Link]();
Thread[] listOfThreads = newThread[numThreads];
[Link](listOfThreads);
for (int i = 0; i < numThreads; i++)
[Link]("Thread #" + i + " = " +
listOfThreads[i].getName());
}
}
METODECAREFUNCȚIONEAZĂPEGRUPULDEFIRE
• getMaxPriority(), setMaxPriority(int)
• isDaemon(), setDaemon(boolean)
Un grup de fire daemon este unul care se distruge singur atunci când ultimul său fir/grup este distrus.
• getName() // name of the thread
• getParent() ș i parentOf(ThreadGroup) // boolean
• toString()
• activeCount(), activeGroupCount()
• // # de fire descendente active ș i grupuri
• suspend(); //depreciat; suspenda toate firele din acest grup.
• resume();
• opreș te();