tema 4: control del flujo de ejecución: excepciones y …poo-2006-2007]tema4.pdf · concurrencia :...
TRANSCRIPT
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