Tema 4: Control del flujo de ejecución: Excepciones y …POO-2006-2007]Tema4.pdf · Concurrencia :...

19
1 { MARCOS LOPEZ SANZ } { MARCOS LOPEZ SANZ } Kybele, 2007 © Tema 4: Control del flujo de ejecución: Excepciones y Threads Programación Orientada a Objetos Marcos López Sanz Máster en Informática Gráfica, Juegos y Realidad Virtual Kybele, 2007 © { MARCOS LOPEZ SANZ } { MARCOS LOPEZ SANZ } Excepciones Def.: Problemas que ocurren durante la ejecución de un programa o aplicación En Java: Objeto que define una situación inusual o érronea y que son lanzadas por un programa o el entorno de ejecución Tipos: Excepciones: pueden ser capturadas y manejadas por el programa en ejecución Errores: representan situaciones irrecuperables y no deberían ser capturadas Formas de actuación frente a excepciones: A. Ignorarlas B. Tratarlas donde ocurren C. Tratarlas en otro punto del programa Propagación

Transcript of Tema 4: Control del flujo de ejecución: Excepciones y …POO-2006-2007]Tema4.pdf · Concurrencia :...

1

{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ } Kybele, 2007 ©

Tema 4: Control del flujo de ejecución: Excepciones y Threads

Programación Orientada a ObjetosMarcos López Sanz

Máster en Informática Gráfica, Juegos y Realidad Virtual

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Excepciones

� Def.: Problemas que ocurren durante la ejecución de un programa o aplicación

� En Java: Objeto que define una situación inusual o érronea y que son lanzadas por un programa o el entorno de ejecución

� Tipos:� Excepciones: pueden ser capturadas y manejadas por el programa en ejecución� Errores: representan situaciones irrecuperables y no deberían ser capturadas

� Formas de actuación frente a excepciones:A. IgnorarlasB. Tratarlas donde ocurrenC. Tratarlas en otro punto del programa � Propagación

2

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Tratamiento de excepciones:

Opción A: Ignorar

� Si una excepción no se captura el programa termina (‘ended abnormally’)

� Toda sentencia que aparece después del punto donde se produjo el problema no se ejecuta*

� Se suele mostrar un mensaje descriptivo de la excepción ocurrida:

java.lang.ArithmeticException: / by zero

at Ejemplo1.main(Ejemplo1.java:5)

Nombre de la clase de excepción Mensaje descriptivo

Pila de llamadas

Método donde se produjo el error

Fichero que contiene la clase

Última línea ejecutada (causa)

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

public class Ejemplo1

{

public static void main()

{

int i = 10/0;

}

}

java.lang.ArithmeticException: / by zero

at Ejemplo1.main(Ejemplo1.java:21)

Tratamiento de excepciones:

Opción A: Ignorar

3

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Tratamiento de excepciones:

Opción B: Captura y manejo

Sentencia try-catch-finally:

� try {…}

� Delimita un bloque de sentencias que pueden dar lugar a un error (lanzar una excepción)

� catch (<claseExcepcion> objExc){…}

� Bloque en el que se define cómo debe tratarse la excepción� Se pueden anidar varios tipos de excepciones (de la más concreta a la más

general o por orden de preferencia de tratamiento)

� finally {…}

� Bloque de código que siempre se ejecuta� Se suele utilizar para continuar la ejecución “estable” de un programa

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Tratamiento de excepciones:

Opción B: Captura y manejo

public class Ejemplo2

{

public static void main()

{

int numerador = 5;

int denominador = 0;

try {

int resultado = numerador/denominador;

System.out.println("Resultado: " + resultado);

}

catch (ArithmeticException ex){

System.out.println("Error!!!!!");

}

finally{

System.out.println("Esto siempre se ejecuta");

}

}

}

4

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Tratamiento de excepciones:

Opción B: Captura y manejo

public class Ejemplo3

{

public static void main()

{

int numerador = 5;

int[] denominador = new int[2];

try {

denominador[0] = 0;

int resultado = numerador/denominador[2];

System.out.println("Resultado: " + resultado);

}

catch (ArithmeticException ex){

System.out.println("Error aritmético!!!!!");

}

catch (Exception ex){

System.out.println("Error general!!!!!");

}

finally{

System.out.println("Esto siempre se ejecuta");

}

}

}

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Tratamiento de excepciones:

Opción C: Propagación

� Propagación: consiste en capturar la excepción externamente al método en el que se produce la excepción

� La excepción se propaga hasta que es capturada o hasta que llega al método main(equivalente a ignorarla)

public class Ejemplo3

{

public Ejemplo3() {}

public static void main()

{

Ejemplo3 obj3 = new Ejemplo3();

obj3.metodo1();

}

}

5

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Tratamiento de excepciones:

Opción C: Propagación

public void metodo1(){

//try {

this.metodo2();

//}

//catch (ArithmeticException ex){

System.out.println("Error aritmético!!!!!");

//}

}

public void metodo2(){

this.metodo3();

}

public void metodo3(){

int error = 3/0;

}

java.lang.ArithmeticException: / by zero

at Ejemplo3.metodo3(Ejemplo3.java:18)

at Ejemplo3.metodo2(Ejemplo3.java:14)

at Ejemplo3.metodo1(Ejemplo3.java:7)

at Ejemplo3.main(Ejemplo3.java:24)

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Jerarquía de errores y excepciones (Incompleta)

Object

Throwable

AWTError

LinkageError

ThreadDeath

Error Exception

VirtualMachineError

ClassNotFoundException

NoSuchMethodException

RuntimeException

ArithmeticException

IndexOutOfBoundsException

NullPointerException

6

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Clases Exception y Throwable

� Clase Exception (java.lang): constructores:� Exception ()

� Exception (String mensaje)

� Exception (String mensaje, Throwable causa)

� Exception (Throwable causa)

� Clase Throwable (java.lang): clase base de Error y Exception� getCause(): devuelve un objeto Throwable que representa la excepción

que lo lanzó� getMessage(): String con una breve descripción de la excepción (o

error)� printStackTrace(): String con la traza de invocaciones actuales

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Creación y lanzamiento de excepciones

� Para crear una excepción personalizada hay que crear una clase que herede de Exception:

public class ExcepcionPropia extends Exception

{

public ExcepcionPropia(String mensaje)

{

super(mensaje);

}

}

� Lanzamiento de excepciones (propias o predefinidas)throw refObjetoExcepcion

…ExcepcionPropia fallo;

fallo = new ExcepcionPropia(“Esto es un error”);

throw fallo;

… El resto de sentencias no se ejecutarán

7

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Tipos de excepciones

� Tipos de excepciones:� Unchecked o en tiempo de ejecución: son aquellas producidas dentro del entorno de ejecución

de Java (aritméticas, puntero a null, índice no válido, etc.)� Checked o no dependientes de la ejecución: son aquellas cuya causa no depende directamente

del entorno de ejecución (p.ej. errores de entrada/salida)

� Las excepciones no dependientes de la ejecución siempre hay que capturarlas o decir que el método lanza la excepción no controlada

� Cuando no se captura una excepción es posible hacer que el método en el que se produce lance una excepción determinada (checked o unchecked):

public void metodo3() throws ArithmeticException{

int error = 3/0;

}

� Es posible que un método lance más de una excepción (se separan por comas)

public void escribirArrayEnFichero() throws IOException, ArrayIndexOutOfBoundsException

{…}

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Excepciones más comunes

� Excepciones� ArithmeticException: Errores de cálculo� IndexOutOfBoundsException: Índices mal usados en arrays, strings o

vectores� ClassNotFoundException: clase no encontrada� FileNotFoundException: fichero no encontrado� InvalidParameterException: El argumento pasado no es válido� NullPointerException: Referencia a un objeto vacío� IOException: error de entrada/salida

� Errores:� AbstractMethodError: intento de instanciar una clase abstracta� InternalError: error interno del intérprete� UnknownError: error desconocido� OutOfMemoryError: la máquina virtual se ha quedado sin memoria

8

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Threads: introducción

� Def1.: Camino seguido por un programa durante su ejecución

� Def2.: Sección de código ejecutado independientemente de otros hilos de ejecución en un úúnico programanico programa

� Necesidad: realizar múltiples tareas simultáneamente para obtener un objetivo o resultado

� Concurrencia: ante la ejecución de diferentes hilos de ejecución existe un “planificador”(scheduler) dentro de la máquina virtual de Java que es quien selecciona la tarea a ejecutar en cada momento.

� La concurrencia en java se basa en threads o “procesos ligeros”. En otros lenguajes o sistemas, la concurrencia se basa en una replicación de datos y código en contextos diferentes, en Java son controlados por un proceso único: la máquina virtual de Java

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Threads: ciclo de vida

Nuevo thread

Parado

Ejecutable En ejecución

MUERTOMUERTOBloqueado

yield()planifi

cador

notify() /notifyAll()

interrupt()Fin de sleep()

start()

Object.wait()Thread.sleep()

Respuesta de E/S o liberación del bloqeo

destroy()

Bloqueo externo al thread

Fin de run()

EN ESPERAEN ESPERA

VIVOVIVO

destroy()Cierre E/S

9

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Threads: definición

� La definición de un thread siempre está asociada a una determinada clase

� Dos formas:� Crear una clase que herede de Thread (java.lang.Thread)� Implementar el interfaz Runnable

� Ambas opciones de creación son equivalentes:� Si se usa extends la clase no puede heredar de ninguna más pero sí implementar

otros interfaces� Si se usa implements, la clase puede heredar de otra clase e implementar otros

interfaces

� Método heredado: run()� Corresponde al “main” de un thread� Es público, devuelve void y no admite argumentos� No se permite que lance excepciones (throw)

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Threads: definición (ejemplos)

� public class PruebaThread1 extends Thread {

public void run(){…}

}

� public class PruebaThread2 implements Runnable {

Thread th;

public void run(){

this.th = Thread.currentThread();

…}

}

10

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Estados de un thread:

Nuevo Thread

� Para la creación de un nuevo thread hay que instanciar una clase que tenga las propiedades de Runnable:

PruebaThread1 th1 =

new PruebaThread1(“primer thread”);

� Se trata de una instancia que no está en ejecución, es una referencia a un futuro hilo de ejecución

� Sólo admite los métodos� start(): inicia la ejecución del código asociado al thread y pasa al estado

“ejecutable”� stop(): deprecated. No se recomienda su uso. Pasaría a estado “muerto”

� La invocación de cualquier otro método de la clase lanzaría la excepción IllegalThreadStateEsception

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Estados de un thread:

Ejecutable/En ejecución

� Una vez se ha creado la referencia al thread a ejecutar y se ha lanzado el método start() ocurre lo siguiente:� Se reservan los recursos necesarios para la ejecución del thread� Se añade el thread a la lista de procesos seleccionables por el planificador� Se invoca el método run() definido en la clase del thread cuyas sentencias se

ejecutan secuencialmente

� Estados:� “Ejecutable” quiere decir que el thread está a la espera de que el planificador lo

lleve a ejecución� “En ejecución” quiere decir que se están ejecutando las sentencias del thread

11

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Estados de un thread:

Ejecutable/En ejecución

� Admite los siguientes métodos:� sleep(msec) de la clase Thread o wait(msec) de la clase Object: en ambos casos pasa a

estado “parado”� destroy()(no implementado): pasa a estado “muerto”� yield(): si está “en ejecución” pasa a estar en estado “ejecutable” (pierde el control del

procesador y tiene que esperar a que el planificador lo elija), al revés no tiene efecto

� También puede pasar a estado bloqueado:� Esperando por una respuesta a una operación de Entrada/Salida � Entrar en una condición de sincronización

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Estados de un thread:

Parado

� En este estado, el thread no puede realzar ninguna operación� Origen y causa de evolución de estado

� wait()� si alguien invoca el método notify() sobre el thread o notifyAll() en general

� sleep()� cuando termine el tiempo establecido en el parámetro o si se invoca interrupt() sobre el thread

� En ambos casos, al salir de este estado siempre se pasa a “ejecutable”

12

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Estados de un thread:

Bloqueado

� Se entra en este estado cuando el thread está esperando por alguna condición que es externa a la máquina virtual � Normalmente son condiciones de Entrada/Salida

� Evolución desde este estado:� A “ejecutable”: cuando se obtiene la respuesta de la entrada/salida� A “muerto”: cuando se invocan los métodos stop() (deprecated) o destroy() (no

implementado) o bien algún otro thread cierra el canal de E/S por el que espera el threadbloqueado

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Estados de un thread:

Muerto

� Condiciones de llegada� Desde cualquier estado al invocar stop() (deprecated) o destroy() (no

implementado)

� Desde “ejecutable/en ejecución”: se llega al final del método run()

13

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Threads:

Prioridades y programación de tareas

� La ejecución simultánea de varios threads es posible en máquinas monoprocesador por la existencia de un planificador que escoge el thread a ejecutar en cada momento

� Todo thread tiene una prioridad en función de la cual elige el planificador: � MIN_PRIORITY (0), � NORM_PRIORITY (5)� y MAX_PRIORITY (10)

� La prioridad puede ser establecida con setPriority(intprioridad)

� Ante una misma prioridad se elige aleatoriamente

� Un thread puede dejar de estar en ejecución voluntariamente invocando el método yield()

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Threads:

Resumen de métodos principales

� Object:� wait(): bloquea un thread indefinidamente � notify(): desbloquea un thread parado con wait()� notifyAll(): desbloquea todos los threads

� Thread� start(): comienza la ejecución de un thread� yield(): pasa del estado “en ejecución” a estado “ejecutable”� sleep(int msec): bloquea el thread los miliseg. indicados� interrupt(): desbloquea un thread parado con sleep()� isAlive(): devuelve true si un thread está en estado ejecutable/en ejecución,

parado o bloqueado. false en otro caso� run(): método que contiene el conjunto de sentencias a ejecutar� currentThread(): devuelve un objeto thread que representa al hilo de

ejecución actual

14

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Sincronización entre threads

� Necesidad: Existencia de “condiciones de carrera” � problemas en los cuales dos o más threads están leyendo o escribiendo datos compartidos y el resultado final depende de la planificación de ejecución

� Problemas de sincronización: resultados de ejecución inesperados (diferentes cada vez)

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Problemas de sincronización:

Ejemplo (clase Productor)

public class Productor extends Thread {

ObjComun destino;

public Productor (ObjComun objCompartido) {

this.destino = objCompartido;

}

public void run() {

for (int i = 0; i < 10; i++) {

try {

System.out.println (“Productor pone:"+i);

destino.put(i);

sleep(10);

} catch (InterruptedException e) { }

}

}

}

15

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Problemas de sincronización:

Ejemplo (clase Consumidor)

public class Consumidor extends Thread {

ObjComun origen;

public Consumidor (ObjComun objCompartido) {

this.origen = objCompartido;

}

public void run() {

for (int i = 0; i < 10; i++) {

try {

System.out.println ("Consumidor quita:"+origen.get());

sleep(10);

} catch (InterruptedException e) { }

}

}

}

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Problemas de sincronización:

Ejemplo (clase ObjComun)

public class ObjComun

{

public int actual, ultimo = 0;

public int[] arrayComun = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};

public ObjComun(){

this.actual=0;

}

public void put(int x) {

ultimo=actual;

this.arrayComun[actual++]=x;

}

public int get(){

return this.arrayComun[ultimo];

}

}

16

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Problemas de sincronización:

Ejemplo (clase principal)

public class EjemploSinc {

public static void main() {

ObjComun o = new ObjComun();

Productor p = new Productor(o);

Consumidor c = new Consumidor(o);

p.start();

c.start();

}

}

Consumidor quita: -1Consumidor quita: -1productor pone: 0Consumidor quita: 0productor pone: 1Consumidor quita: 1Consumidor quita: 1productor pone: 2Consumidor quita: 2productor pone: 3Consumidor quita: 3productor pone: 4Consumidor quita: 4productor pone: 5productor pone: 6Consumidor quita: 6productor pone: 7Consumidor quita: 7productor pone: 8productor pone: 9

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Sincronización y comunicación

� Solución:� Los threads no deben acceder simultáneamente al objeto compartido � hay que

bloquear el acceso

<visibilidad> synchronized <tipo><idMétodo>(<param.>){…}

� Mientras un thread ejecuta un método synchronized el resto de threads no puede acceder a ese objeto (estado “bloqueado” � bloqueado por algo externo al thread)

� Entre varios threads colaboradores debe existir una comunicación � uso de esperas (wait) y notificaciones (notify/notifyAll)

17

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

public synchronized int get() {try {

while (disponible == false) {wait();

}} catch (InterruptedException e) { }

disponible = false;notifyAll();return this.arrayComun[ultimo];

}

public synchronized void put(int x) {try {

while (disponible == true) {wait();

}} catch (InterruptedException e) { }disponible = true;ultimo=actual;this.arrayComun[actual++]=x;notifyAll();

}

Threads:

Comunicación y sincronización

productor pone: 0productor pone: 1Consumidor quita: 0Consumidor quita: 1productor pone: 2productor pone: 3productor pone: 4Consumidor quita: 2Consumidor quita: 3productor pone: 5Consumidor quita: 4Consumidor quita: 5productor pone: 6Consumidor quita: 6productor pone: 7Consumidor quita: 7productor pone: 8Consumidor quita: 8productor pone: 9Consumidor quita: 9

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Threads: Miscelánea

� Diferencia entre wait() y sleep(): wait libera el bloqueo sobre el objeto, sleepno

� Nunca se puede hacer: objThread.run();� Deadlock: situación en la que varios threads se bloquean en espera de que el

otro libere el recurso� Why are Thread.stop, Thread.suspend,

Thread.resume and Runtime.runFinalizersOnExit deprecated?:

����http://java.sun.com/j2se/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html

� Grupos de threads:� Ejemplo:

ThreadGroup miGrupo = new

ThreadGroup(“miGrupoDeThreads”);

Thread th1= new Thread(miGrupo,“Thread 1”);

� Permite agrupar threads para poder lanzarles mensajes a todos a la vez:miGrupo.interrupt();

18

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Threads:

Excepciones asociadas a threads

� SecurityException: lanzada cuando no se puede lanzar un método sobre un thread determinado por no tener permisos sobre él

� InterruptedException: lanzada cuando se desbloquea un thread parado con sleep()

� IllegalThreadStateException: lanzada cuando se intenta lanzar start() sobre un thread ya inicializado

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Ejercicio

� Implementar la clase ColaDeEnteros (capacidad máxima 500) en la cual los métodos poner() y quitar() están sincronizados.

� Crear 2 clases de acceso a la ColaDeEnteros. Los objetos de ambas clases se identifican por un número entero.� Generador: Inserta elementos en la cola siempre que haya menos de 10 enteros y hasta que

se llena. En caso contrario, espera. � Impresora: Lee e imprime por pantalla los elementos de la cola siempre que haya elementos.

Si no hay elementos, espera. Completará 150 iteraciones.

� Parte A: crear 1 objeto Generador y 1 objeto Impresora. Cada uno completará100 iteraciones

� Parte B: crear 5 objetos Generador y 5 objetos Impresora. Cada uno completará 50 iteraciones. Los generadores comenzarán por el número que les identifique como generador x100

19

Kybele, 2007 ©{ MARCOS LOPEZ SANZ }{ MARCOS LOPEZ SANZ }

Bibliografía

� Java software solutions, foundations of program design (3rd edition). J. Lewis & W. Loftus. Ed. Addison-Wesley, 2004. Cap. 8 (pp. 448-460)

� Java and Object Orientation: an introduction. J. Hunt. Ed. Springer-Verlag, 1998. Cap. 25 (pp. 319-317)

� Java threads (2nd edition). S. Oaks & H. Wong. Ed. O’Reilly, 1999.

� Big Java: programming and practice. C. Horstmann. Ed. John Wiley& Sons, 2002. Cap. 14 y 21.

� http://java.sun.com/j2se/1.4.2/docs/api/java/lang/� Throwable.html

� Exception.html

� Error.html

� Thread.html