Sunteți pe pagina 1din 44

Proiectarea aplicațiilor orientate

obiect
Curs 9 – exceptii, fire de executie

J
J Acest curs
› Tratarea excepțiilor
› Controlul firelor de execuție
J Definiție
› O excepție este un eveniment “excepțional” care se produce în
timpul rulării unui program și care întrerupe execuția normală a unui
program.
› Ex:
– nu s-a putut deschide fișierul de lucru
– s-a depășit dimensiunea tabloului de elemente

› Tipuri de excepții
J Java Built-in Exceptions - examples
Arithmetic Exception
It is thrown when an exceptional condition has occurred in an arithmetic operation.
ArrayIndexOutOfBoundException
It is thrown to indicate that an array has been accessed with an illegal index. The index is either negative or
greater than or equal to the size of the array.
ClassNotFoundException
This Exception is raised when we try to access a class whose definition is not found
FileNotFoundException
This Exception is raised when a file is not accessible or does not open.
IOException
It is thrown when an input-output operation failed or interrupted
InterruptedException
It is thrown when a thread is waiting , sleeping , or doing some processing , and it is interrupted.
NoSuchFieldException
It is thrown when a class does not contain the field (or variable) specified
NoSuchMethodException
It is thrown when accessing a method which is not found.
NullPointerException
This exception is raised when referring to the members of a null object. Null represents nothing
NumberFormatException
This exception is raised when a method could not convert a string into a numeric format.
RuntimeException
This represents any exception which occurs during runtime.
StringIndexOutOfBoundsException
It is thrown by String class methods to indicate that an index is either negative than the size of the string
J Raportare excepție

public class Main {


public static void main(String[] args) {
int []v = new int[5];
v[5] = 10;
}
}

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5


out of bounds for length 5
at HelloWorld.Main.main(Main.java:8)
J Tratarea excepțiilor
› Crearea unui obiect de tip excepţie se asociază cu aruncarea unei
excepţii ("throwing an exception").
› În momentul în care o metodă generează o excepție (sau aruncă o
excepţie) sistemul de execuţie este responsabil cu găsirea unei
secvenţe de cod dintr-o metodă care să trateze respectiva excepţie.
› Căutarea se face recursiv, începând cu metoda care a generat
excepţia şi mergând înapoi pe linia apelurilor către metoda care
poate rezolva exceptia respectiva.
› Secvența de cod dintr-o metodă care tratează o anumită excepţie se
numeşte analizor de excepție ("exception handler") iar
interceptarea şi tratarea excepției se numeste prinderea excepţiei
("catch the exception").
J ”Prinderea” și ”tratarea” excepțiilor
› Secvența de cod șablon pentru prinderea și tratarea excepțiilor este:
try {
Instrucţiuni care pot genera o excepţie
}
catch (ExceptieSpecifica e ) {
Prelucrarea excepţiei de tipul ExceptieSpecifica
}
catch (AltaExceptie e) {
Prelucrarea excepţiei de tipul AltaExceptie
}
catch (ExceptieGenerala e) { //c++ catch (...) {
Prelucrarea excepţiei de tipul ExceptieGenerala
}
finally {
Cod care se execută indiferent dacă apar sau nu excepţii
}
J Exemplu de generare și prindere de excepții
public class Main {
public static void main(String[] args) {
int x = (int)(Math.random()*5);
int y = (int)(Math.random()*10);
int []z = new int[5];
try {
System.out.println("y/x = " + y/x);
System.out.println("z[y] = " + z[y]);
}
catch(ArithmeticException e) {
System.out.println("ArithmeticException:" + e);
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println("ArrayIndexOutOfBoundsException:" + e);
}
}
}
J Rezultate ale rularii exemplului
› First run y/x = 0
z[y] = 0

› Second run
y/x = 7
ArrayIndexOutOfBoundsException:java.lang.ArrayIndexOutOfBound
sException: Index 7 out of bounds for length 5

› Third run ArithmeticException:java.lang.ArithmeticException: / by zero


›…
› Odată ce o excepție este aruncată restul liniilor de cod din blocul try nu
mai sunt executate
J public class Main {
public static void main(String[] args) {
int x = (int)(Math.random()*5);
int y = (int)(Math.random()*10);
int []z = new int[5];
try {
System.out.println("y/x = " + y/x);
System.out.println("z[y] = " + z[y]);
}/*
catch(ArithmeticException e) {
System.out.println("ArithmeticException:" + e);
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println("ArrayIndexOutOfBoundsException:" + e);
}*/
finally {

}
}
}
J
› … run y/x = 2
z[y] = 0

› … run y/x = 1
Exception in thread "main"
java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds
for length 5
at HelloWorld.Main.main(Main.java:192)

› … run Exception in thread "main" java.lang.ArithmeticException: / by


zero
at HelloWorld.Main.main(Main.java:191)
J public class Main {
public static void main(String[] args) {
int x = (int)(Math.random()*5);
int y = (int)(Math.random()*10);
int []z = new int[5];
try {
System.out.println("y/x = " + y/x);
System.out.println("z[y] = " + z[y]);
}/*
catch(ArithmeticException e) {
System.out.println("ArithmeticException:" + e);
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println("ArrayIndexOutOfBoundsException:" + e);
}*/
finally {
System.out.println(“Exceptii netratate");
}
}
}
J
› … run Exceptii netratate
Exception in thread "main" java.lang.ArithmeticException: / by zero
at HelloWorld.Main.main(Main.java:191)

› … run y/x = 2
Exceptii netratate
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
Index 7 out of bounds for length 5
at HelloWorld.Main.main(Main.java:192)

› … run y/x = 0
z[y] = 0
Exceptii netratate

› Blocul finally se va executa întotdeauna.


J
public class Main {
public static void main(String[] args) {
System.out.println(print());
}
public static String print()
{
try
{
System.out.println("Executa blocul try");
return “Return din blocul try";
}
finally
{
System.out.println(“Executa blocul finally");
}
} Executa blocul try
} Executa blocul finally
Return din blocul try
J
public class Main {
public static void main(String[] args) {
System.out.println(print());
}
public static String print()
{
try
{
System.out.println("Executa blocul try");
return "Return din blocul try";
}
finally
{
System.out.println("Executa blocul finally");
return "Return din blocul finally";
} Executa blocul try
} Executa blocul finally
} Return din blocul finally
J Ierarhia claselor ce descriu exceptii
J Ierarhia claselor ce descriu excepții
› Throwable este clasa de bază din care sunt derivate excepțiile.
– Erorile de sistem sunt aruncate de JVM și reprezentate în clasa Error. Aceste erori
apar rar. În situația în care apar, utilizatorul trebuie notificat, iar programul se va
încheia. VirtualMachineError apare atunci când JVM este blocat sau când nu
mai are resurse pentru a rula programul;

– Excepțiile sunt reprezentate în clasa Exception, care descrie erori cauzate de


program și de circumstanțe externe. Aceste erori pot fi prinse în program. Exemple
ar fi ClassNotFoundException sau IOException, legate de operații invalide de
input și output. Subclase ale lui IOException sunt InterruptedIOException,
EOFException sau FileNotFoundException;
J Checked vs Unchecked exception
J Checked vs Unchecked exception
› Checked – excepții verificate în momentul compilării: Dacă o secvență
de cod dintr-o metodă aruncă “checked exception” atunci metoda
trebuie ori să gestioneze excepția respectivă ori trebuie specificat că
aruncă o excepție folosind cuvântul cheie throws.
public class Main {
public static void main(String[] args) {
FileReader file = new FileReader("C:\\test\\a.txt");
BufferedReader fileInput = new BufferedReader(file);
for (int counter = 0; counter < 3; counter++)
System.out.println(fileInput.readLine());
fileInput.close();
}
}
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code
- unreported exception java.io.FileNotFoundException; must be caught or declared
to be thrown at Main.main(Main.java:5)
public static void main(String[] args) throws IOException {
J Checked vs Unchecked exception
› Unchecked – excepții care nu sunt verificate în momentul compilării
› Clasele Error & RuntimeException sunt excepții unchecked
class Main {
public static void main(String args[]) {
int x = 0;
int y = 10;
int z = y/x;
}
}

Exception in thread "main" java.lang.ArithmeticException: / by zero at


Main.main(Main.java:5)
J Lucru cu excepții
› Declararea excepțiilor
– Fiecare metodă trebuie să precizeze tipul de excepție checked pe care o aruncă.

public void myMethod() throws Exception1, Exception2, ..., ExceptionN

– Java nu impune declararea excepțiilor unchecked.

– Dacă o metodă nu declară excepțiile în clasa de bază, atunci nu poate fi suprascrisă


să declare excepțiile în subclasă
J Aruncarea excepțiilor
› Un program care detectează o eroare poate crea o instanță a excepției și
să o arunce.
throw new IllegalArgumentException("Wrong Argument");

› IllegalArgumentException este o clasă excepție în Java.


› Fiecare clasă excepție are doi constructori – unul fără parametri și unul
cu un parametru de tipul String ce descrie excepția.
› Argumentul este numit exception message și poate fi obținut folosind
apelul getMessage()
J Custom exception or user-defined exception
› Este de preferat să se folosească clasele de excepții definite de
Java, în locul creării unora noi.
› Se pot crea noi clase de excepții, derivate din Exception sau din
subclasele ei, cum ar fi IOException și sunt excepții checked
› Exception moștenește pe Throwable, din care preia metodele
getMessage(), toString() și printStackTrace().
– getMessage() returnează mesajul obiectului
– toString() returnează o concatenare a numelui clasei și a mesajului returnat de
getMessage()
– printStackTrace() afișează apelurile pe stivă ale metodelor.
› Clasa Exception are 4 constructori, dintre care cei mai des utilizați
sunt constructorul fără parametri și cel cu parametru de tip String
J Custom exception or user-defined exception
class InvalidAgeException extends Exception {

InvalidAgeException(String s){
super(s);
}
}

class TestCustomException {

static void validate(int age) throws InvalidAgeException {


if (age < 18)
throw new InvalidAgeException("not valid");
else
System.out.println("welcome to vote");
}
}
J Custom exception or user-defined exception
public class Main {

public static void main(String[] args) {

try{
TestCustomException.validate(13);
}
catch(Exception m){
System.out.println("Exception occured: "+m);
}
}
}

Exception occured: HelloWorld.InvalidAgeException: not valid


J Ierarhii de exceptii
› Fie ierarhia de clase:
class TemperatureException extends Exception {...}
class TooColdException extends TemperatureException {...}
› Prinderea exceptiilor se face in ordinea inversa definirii ierarhiei
try {
...
}
catch (TooColdException e) {
...
}
catch (TemperatureException e) {
...
}
catch (Exception e) { //c++ catch(...)
...
}
J Fire de execuție
› Unul dintre avantajele limbajului de programare Java este posibilitatea
de a rula task-uri concurente într-un program. Acest procedeu se
numește multithreading.
› Un fir de execuție (thread) reprezintă fluxul de execuție, de la început la
final, al unui task.
› Aceste fire se pot executa simultan în sistemele multiprocesor.
› În sistemele single-procesor, mai multe fire de execuție împart timpul
procesorului, iar sistemul de operare este responsabil pentru împărțirea
și alocarea resurselor.
› Când programul se execută, interpretorul Java pornește un fir de
execuție pentru metoda main.
J Fire de execuție
› Programare concurentă
› Firele de execuţie fac trecerea de la programarea secvenţială la
programarea concurentă.
› Un fir de execuţie este o succesiune secvenţială de instrucţiuni care se
execută în cadrul unui proces.

› Proces – mai multe fire de execuție


J Proces vs fir(e) de execuție
› Asemănări
– Concurență
– Planificare la execuție
› Deosebiri
– Un fir de execuţie poate exista doar într-un proces
– Proces nou: cod + date
– Fir nou: toate firele de execuţie au acces la aceleaşi date, datele procesului original.
› Utilitate
– Calcule matematice
– Utilizarea unor resurse
– GUI
J Crearea unui fir de execuție
› extinderea clasei Thread
› implementarea interfeţei Runnable
› Clasa Thread
– implementează un fir de execuţie generic care, implicit, nu face nimic
› Interfața Runnable
– Defineşte un protocol comun pentru obiecte active
– Conţine metoda run
– Este implementată de clasa Thread
J Extinderea clasei Thread
public class FirExecutie extends Thread {
public FirExecutie(String nume) {
super(nume);
}
public void run() {
...
}
}

public class Main {


public static void main(String[] args) {
FirExecutie fir = new FirExecutie("simplu");
fir.start();
}
}
J Extinderea clasei Thread - exemplu
class Count extends Thread {
private int a, b, step;
public Count(int a, int b, int pas, String name ) {
super(name);
this.a = a;
this.b = b;
this.pas = step;
}
public void run () {
for (int i = a; i <= b; i += step)
System.out.print(i + ", " );
}
}
J Extinderea clasei Thread - exemplu

public class Main {


public static void main(String[] args) {
Count f1, f2 ;
f1 = new Count (0, 10000 , 1, new String("F1"));
f2 = new Count (100 , 200 , 10, new String("F2"));
f1.start ();
f2.start ();
}
}

0, 100, 1, 110, 2, 120, 3, 130, 4, 140, 5, 150, 6, 160, 7, 170, 8, 180,


9, 190, 10, 200, 11,
J Implementarea interfeței Runnable

public class MyClass implements Runnable {


public void run() {
...
}
}

public class Main {


public static void main(String[] args) {
MyClass myObj = new MyClass();
Thread f = new Thread(myObj);
f.start();
}
}
J Implementarea interfetei Runnable
public class FirExecutie implements Runnable {
private Thread fir = null;
public FirExecutie() {
fir = new Thread(this);
}
public void run() { ... }
}

public class Main {


public static void main(String[] args) {
FirExecutie fir = new FirExecutie();
f.start();
}
}
J Ciclu de viață
› Starea “New Thread”
Threar f = new Thread(obj);
//f se gaseste in starea “New Thread”
› Nu are alocate resurse
› Se poate apela start
› IllegalThreadStateException
J Ciclu de viață
› Starea “Runnable”
f.start(); //f se gaseste in starea "Runnable“
– Alocare resurse
– Planificare la procesor

› Apel run Starea ”Not Runnable”


– Firul de execuție se afla în sleep mode;
try {
Thread.sleep(1000);
}
catch (InterruptedException e) { ...}

– S-a apelat metoda .wait()


– Este blocat într-o operaţie de intrare/ieşire.
J Ciclu de viață
› Starea “Dead”
› Firele de execuție trebuie să se “termine singure”
› Nu exista metoda stop
public void run() {
for(int i = a; i <= b; i += step)
System.out.print(i + " " );
}
› Quit flag public boolean executie = true;
public void run() {
while (executie) {
...
}
}

› System.exit termină forţat toate firele de execuţie.


J Metode pentru controlul firelor de executie
Metodă Scop
Thread () Creează un thread gol
Thread (Runnable task) Creează un thread pentru un task specificat

void start () Pornește thread-ul și metoda run() este invocată de către JVM

boolean isAlive() Verifică dacă thread-ul rulează


void setPriority (int p) Setează o prioritate p (de la 1 la 10) pentru acest thread

void join() Așteaptă ca acest thread să se finalizeze


void sleep (long ms) Pune un thread în modul sleep pentru un anumit timp specificat în
milisecunde
void yield () Cauzează un thread să se oprească temporar și permite altora să fie
executate
void interrupt () Întrerupe thread-ul
J Metoda .isAlive()
› true - ”Runnable” sau ”Not Runnable”
› false - ”New Thread” sau ”Dead”
Count f = new Count();
f.isAlive(); //retuneaza false (starea este New Thread)

f.start();
f.isAlive(); // retuneaza true (starea este Runnable)

f.executie = false;
f.isAlive(); // retuneaza false (starea este Dead)
J .yield() – lasă alte thread-uri să se execute
public void run() {
for (int i = 1; i <= N; i++) {
System.out.print(" " + i);
f.yield();
}
}

› Firul de execuție f nu își mai folosește întreg timpul procesor ci lasă


timp pentru celelalte
.sleep(…) – pune în modul sleep firul curent
J pentru un număr precizat de secunde
public void run() {
try{
for (int i = 1; i <= N; i++) {
System.out.print(" " + i);
if (i >= 100)
Thread.sleep(1000);
}
}
catch (InterruptedException ex) {

}
}

› Metoda .sleep() poate arunca excepția InterruptedException, care


este o excepție checked și trebuie prinsă în blocurile de try-catch.
› InterruptedException apare atunci când este apelată metoda
.interrupt()
J Priorități de execuție
› Modelul cooperativ - în care firele de execuţie decid când să cedeze
procesorul; dezavantajul este că unele fire pot acapara procesorul,
nepermiţând şi execuţia altora până la terminarea lor.
› Modelul preemptiv - ”cuante de timp” - partajare resurse, dezavantajul
fiind nevoia de a sincroniza accesul firelor la resursele comune.
Metoda .setPriority(p); //p = 1 … 10
MAX_PRIORITY = 10;
MIN_PRIORITY = 1;
NORM_PRIORITY= 5;

› Un fir de execuţie cedează procesorul:


– prioritate mai mare
– metoda sa run() se termină
– yield()
– timpul alocat a expirat
J
› Dacă toate thread-urile care rulează au priorități egale, fiecăruia îi
este asignată o cantitate egală din timpul CPU-ului într-o coadă
circulară. Acest procedeu este numit round-robin-scheduling.
› Un fir de execuție poată să nu ajungă să fie executat dacă rulează un
thread cu o prioritate mai mare sau dacă unul cu o prioritate egală nu
apelează .yield() – situație numită starvation
› Pentru a evita, un thread cu o prioritate mare trebuie să invoce
periodic .yield() sau .sleep(…) pentru a da șansa unor
thread-uri de prioritate egală sau mai mică să fie executate

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