La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Sesión 1: Introducción al Lenguaje Java

Presentaciones similares


Presentación del tema: "Sesión 1: Introducción al Lenguaje Java"— Transcripción de la presentación:

1 Sesión 1: Introducción al Lenguaje Java

2 Índice Introducción a Java Conceptos de POO
Elementos de un programa Java Herencia, interfaces, polimorfismo Hilos Clases útiles Java Lenguaje Java 2

3 Java Java es un lenguaje OO creado por Sun Microsystems para poder funcionar en distintos tipos de procesadores y máquinas. Similar a C o C++, pero con algunas características propias (gestión de hilos, ejecución remota, etc) Independiente de la plataforma, gracias a la JVM (Java Virtual Machine), que interpreta los ficheros objeto Se dispone de antemano de la API (Application Programming Interface) de clases de Java. Java Lenguaje Java 3

4 Clases • Clases: con la palabra class y el nombre de la clase •
class MiClase { ... } Como nombre utilizaremos un sustantivo Puede estar formado por varias palabras Cada palabra comenzará con mayúscula, el resto se dejará en minúscula Por ejemplo: DataInputStream Si la clase contiene un conjunto de métodos estáticos o constantes relacionadas pondremos el nombre en plural Por ejemplo: Resources Java Lenguaje Java 4

5 Campos y variables Campos y variables: simples o complejos Utilizaremos sustantivos como nombres Properties propiedades; File ficheroEntrada; int numVidas; Puede estar formado por varias palabras, con la primera en minúsculas y el resto comenzando por mayúsculas y el resto en minúsculas Por ejemplo: numVidas En caso de tratarse de una colección de elementos, utilizaremos plural Por ejemplo: clientes Para variables temporales podemos utilizar nombres cortos, como las iniciales de la clase a la que pertenezca, o un carácter correspondiente al tipo de dato int i; Vector v; DataInputStream dis; Java Lenguaje Java 5

6 Constantes Constantes: Se declarán como final y static
String TITULO_MENU = “Menu”; int ANCHO_VENTANA = 640; double PI = ; El nombre puede contener varias palabras Las palabras se separan con ‘_’ Todo el nombre estará en mayúsculas Por ejemplo: MAX_MENSAJES Java Lenguaje Java 6

7 Métodos • Métodos: con el tipo devuelto, nombre y parámetros •
void imprimir(String mensaje) { ...// Codigo del método } Vector insertarVector(Object elemento, int posicion) Los nombres de los métodos serán verbo Puede estar formados por varias palabras, con la primera en minúsculas y el resto comenzando por mayúsculas y el resto en minúsculas Por ejemplo: imprimirDatos Java Lenguaje Java 7

8 Constructores Constructores: se llaman igual que la clase, y se ejecutan con el operador new para reservar memoria MiClase() { ...// Codigo del constructor } MiClase(int valorA, Vector valorV) ...// Codigo del otro constructor No hace falta destructor, de eso se encarga el garbage collector Constructor superclase: super(…) Java Lenguaje Java 8

9 Paquetes Paquetes: organizan las clases en una jerarquía de paquetes y subpaquetes Para indicar que una clase pertenece a un paquete o subpaquete se utiliza la palabra package al principio de la clase package paquete1.subpaquete1; class MiClase { Para utilizar clases de un paquete en otro, se colocan al principio sentencias import con los paquetes necesarios: package otropaquete; import paquete1.subpaquete1.MiClase; import java.util.*; class MiOtraClase { Java Lenguaje Java 9

10 Paquetes Si no utilizamos sentencias import, deberemos escribir el nombre completo de cada clase del paquete no importado (incluyendo subpaquetes) class MiOtraClase { paquete1.subpaquete1.MiClase a = ...; // Sin import MiClase a = ...; // Con import Los paquetes se estructuran en directorios en el disco duro, siguiendo la misma jerarquía de paquetes y subpaquetes ./paquete1/subpaquete1/MiClase.java Java

11 Paquetes Siempre se deben incluir las clases creadas en un paquete
Si no se especifica un nombre de paquete la clase pertenecerá a un paquete “sin nombre” No podemos importar clases de paquetes “sin nombre”, las clases creadas de esta forma no serán accesibles desde otros paquetes Sólo utilizaremos paquetes “sin nombre” para hacer una prueba rápida, nunca en otro caso Java

12 Convenciones de paquetes
El nombre de un paquete deberá constar de una serie de palabras simples siempre en minúsculas Se recomienda usar el nombre de nuestra DNS al revés especialistajee.org  org.especialistajee.prueba Colocar las clases interdependientes, o que suelan usarse juntas, en un mismo paquete Separar clases volátiles y estables en paquetes diferentes Hacer que un paquete sólo dependa de paquetes más estables que él Si creamos una nueva versión de un paquete, daremos el mismo nombre a la nueva versión sólo si es compatible con la anterior Java

13 Tipo enumerado enum EstadoCivil {soltero, casado, divorciado};
EstadoCivil ec = EstadoCivil.casado; ec = EstadoCivil.soltero; switch(ec) { case soltero: System.out.println("Es soltero"); break; case casado: System.out.println("Es casado"); break; case divorciado: System.out.println("Es divorciado"); break; } Java

14 Otras características
Imports estáticos import static java.lang.Math; double raiz = sqrt(1252.2); Argumentos variables public void miFunc(String param, int... args) { for(int i: args) { … } } Anotaciones (metainformación) Java

15 Convenciones generales
Indentar el código uniformemente Limitar la anchura de las líneas de código (para impresión) Utilizar líneas en blanco para separar bloques de código Utilizar espacios para separar ciertos elementos en una línea Documentación: Utilizar /*... */ para esconder código sin borrarlo Utilizar // ... para detalles de la implementación Utilizar javadoc para describir la interfaz de programación Java

16 Modificadores de acceso
Las clases y sus elementos admiten unos modificadores de acceso: privado: el elemento es accesible sólo desde la clase en que se encuentra protegido: el elemento es accesible desde la propia clase, desde sus subclases, y desde clases del mismo paquete público: el elemento es accesible desde cualquier clase paquete: el elemento es accesible desde la propia clase, o desde clases del mismo paquete. Java

17 Modificadores de acceso
private se utiliza para elementos PRIVADOS protected se utiliza para elementos PROTEGIDOS public se utiliza para elementos PUBLICOS No se especifica nada para elementos PAQUETE public class MiClase { private int n; protected void metodo() { ... } Todo fichero Java debe tener una y solo una clase pública, llamada igual que el fichero (más otras clases internas que pueda tener) Java

18 Modificadores de acceso
La misma Cualquier Subclase de clase clase del otro paquete clase de otro mismo paquete public protected default private Java

19 Otros modificadores abstract: para definir clases y métodos abstractos static: para definir elementos compartidos por todos los objetos que se creen de la misma clase miembros que no pertenecen al objeto en si, sino a la clase dentro de un método estático sólo podemos utilizar elementos estáticos, o elementos que hayamos creado dentro del propio método final: para definir elementos no modificables ni heredables public abstract class MiClase { public static final int n = 20; public abstract void metodo(); ... Java

20 Otros modificadores volatile y synchronized: para elementos a los que no se puede acceder al mismo tiempo desde distintos hilos de ejecución volatile no proporciona atomicidad pero es más eficiente volatile int contador; contador++; //puede causar problemas, son 3 operaciones diferentes synchronized se usa sobre bloques de código y métodos synchronized(this){ contador++; } Java

21 Otros modificadores native: para métodos que están escritos en otro lenguaje, por ejemplo en C++, utilizando JNI (Java Native Interface) transient: para atributos que no forman parte de la persistencia de objeto, para evitar que se serialicen strictfp: evitar que se utilice toda la precisión de punto flotante que proporcione la arquitectura. Usar el estándar del IEEE para float y double. No es aconsejable a menos que sea necesario. Java

22 Herencia y polimorfismo
Herencia: definir una clase a partir de otra existente La nueva clase “hereda” todos los campos y métodos de la clase a partir de la que se crea, y aparte puede tener los suyos propios Ejemplo: a partir de una clase Animal podemos definir otras más concretas como Pato, Elefante… Polimorfismo: si tenemos un método en cualquier clase que sea dibuja (Animal a), podemos pasarle como parámetro tanto un objeto Animal como cualquier subtipo que herede directa o indirectamente de él (Elefante, Pato…) Java

23 Clases abstractas e interfaces
Una clase abstracta es una clase que deja algunos métodos sin código, para que los rellenen las subclases que hereden de ella public abstract class MiClase { public abstract void metodo1(); public void metodo2() { ... } Un interfaz es un elemento que sólo define la cabecera de sus métodos, para que las clases que implementen dicha interfaz rellenen el código según sus necesidades. public interface Runnable { public void run(); } Asignaremos un nombre a los interfaces de forma similar a las clases, pudiendo ser en este caso adjetivos o sustantivos. Java

24 Herencia e interfaces • Herencia Interfaces • •
Definimos una clase a partir de otra que ya existe Utilizamos la palabra extends para decir que una clase hereda de otra (Pato hereda de Animal): class Pato extends Animal Relación “es”: Un pato ES un animal Interfaces Utilizamos la palabra implements para decir que una clase implementa los métodos de una interfaz class MiHilo implements Runnable { public void run() { ... // Codigo del método } Relación “actúa como”: MiHilo ACTÚA COMO ejecutable Java

25 Polimorfismo Si una variable es del tipo de la superclase, podemos asignarle también un objeto de la clase hija Animal a = new Pato(); Si una variable es del tipo de una interfaz implementada por nuestra clase, podemos asignarle también un objeto de esta clase Runnable r = new MiHilo(); Sólo se puede heredar de una clase, pero se pueden implementar múltiples interfaces: class Pato extends Animal implements Runnable, ActionListener Java

26 Punteros this y super this se utiliza para hacer referencia a los elementos de la propia clase: class MiClase { int i; MiClase(int i) { this.i = i; // i de la clase = i del parámetro super se utiliza para llamar al mismo método en la superclase: class MiClase extends OtraClase{ MiClase(int i) { super(i); // Constructor de OtraClase(...) Java

27 Object Clase base de todas las demás
Todas las clases heredan en última instancia de ella Es importante saber las dependencias (herencias, interfaces, etc) de una clase para saber las diferentes formas de instanciarla o referenciarla (polimorfismo) Java

28 Ejemplo de polimorfismo
Por ejemplo, si tenemos: public class MiClase extends Thread implements List Podremos referenciar un objeto MiClase de estas formas: MiClase mc = new MiClase(); Thread t = new MiClase(); List l = new MiClase(); Object o Java

29 Object: objetos diferentes
También es importante distinguir entre entidades independientes y referencias: MiClase mc1 = new MiClase(); MiClase mc2 = mc1; // Es distinto a: MiClase mc2 = (MiClase)(mc1.clone()); El método clone de cada objeto sirve para obtener una copia en memoria de un objeto con los mismos datos, pero con su propio espacio No realiza una copia en profundidad Si queremos hacer copias de los objetos que tenga como campos debe sobrescribir este método Java

30 Object: comparar objetos
Cuando queremos comparar dos objetos entre sí (por ejemplo, de la clase MiClase), no se hace así: if (mc1 == mc2) Sino con su método equals: if (mc1.equals(mc2)) Deberemos redefinir este método en las clases donde lo vayamos a usar, para asegurarnos de que los objetos se comparan bien Notar que la clase String, es un subtipo de Object por lo que para comparar cadenas...: if (cadena == “Hola”) ... // NO if (cadena.equals(“Hola”)) ... // SI Java

31 Object: representar en cadenas
Muchas veces queremos imprimir un objeto como cadena. Por ejemplo, si es un punto geométrico, sacar su coordenada X, una coma, y su coordenada Y La clase Object proporciona un método toString para definir cómo queremos que se imprima un objeto. Podremos redefinirlo a nuestro gusto public class Punto2D { ... public String toString() { return “(“ + x + ”,” + y + ”)”; } Punto2D p = ...; System.out.println(p); // Imprimirá (x, y) del punto Java

32 Properties Esta clase es un tipo de tabla hash que almacena una serie de propiedades, cada una con un valor asociado Además, permite cargarlas o guardarlas en algún dispositivo (fichero) Algunos métodos interesantes: Object setProperty(Object clave, Object valor) getProperty(Object clave) Object default) void load(InputStream entrada) void store(OutputStream salida, String cabecera) Java

33 System Ofrece métodos y campos útiles del sistema, como el ya conocido System.out.println Otros métodos interesantes de esta clase (todos estáticos): void exit(int estado) void gc() long currentTimeMillis() void arrayCopy(Object fuente, int pos_fuente, Object destino, int pos_destino, int numElementos) Java

34 Otras clases La clase Math proporciona una serie de métodos (estáticos) útiles para diferentes operaciones matemáticas (logaritmos, potencias, exponenciales, máximos, mínimos, etc) Otras clases útiles son la clase Calendar (para trabajar con fechas y horas), la clase Currency (para monedas), y la clase Locale (para situarnos en las características de fecha, hora y moneda de una región del mundo) Java

35 Transfer Objects Encapsulan datos con los que normalmente se trabaja de forma conjunta Nos permiten transferir estos datos entre las diferentes capas de la aplicación public class Usuario { private String login; private String password; private boolean administrador; } Java

36 Getters y Setters Es buena práctica de programación declarar todos los campos de las clases privados Para acceder a ellos utilizaremos métodos Getters para obtener el valor del campo Setters para modificar el valor del campo Estos métodos tendrán prefijo get y set respectivamente, seguido del nombre del campo al que acceden, pero comenzando por mayúscula Por ejemplo: getLogin(), setLogin(String login) El getter para campos booleanos tendrá prefijo is en lugar de get Por ejemplo: isAdministrador() Java

37 BeanUtils Utilidades de la biblioteca commons-beanutils de Apache.
BeanUtils.copyProperties(objDestino, objOrigen) Copia los campos comunes entre los dos objetos Los reconoce usando la API de Reflection La identificación está basada en los nombres de los getters y los setters y en su tipo de dato. Ejemplo: int origen.getNombreCampo( ), e void destino.setNombreCampo(int n). Java

38 BeanUtils Ejemplo: proyección de un punto3D en un punto2D.
public class Punto2D { private int x; private int y; private String descripcion; public String getDescripcion() { return descripcion; } public void setDescripcion(String descripcion) { this.descripcion = descripcion; public int getX() { return x; public void setX(int x) { this.x = x; public int getY() { return y; public void setY(int y) { this.y = y; Ejemplo: proyección de un punto3D en un punto2D. En lugar de copiar todos los campos uno a uno: punto2D.setX(punto3D.getX()); punto2D.setY(punto3D.getY()); punto2D.setDescripcion(punto3D.getDescripcion()); public class Punto3D { private int x; private int y; private int z; private String descripcion; /* ...y los getters y setters para los cuatro campos */ } usamos copyProperties: BeanUtils.copyProperties(punto2D, punto3D); Java

39 Lenguaje Java Sesión 2: Colecciones de datos

40 Índice Introducción Colecciones Enumeraciones e iteradores
Polimorfismo e interfaces Wrappers de tipos básicos Java Colecciones - 40

41 Introducción Java proporciona un amplio conjunto de clases útiles para desarrollar aplicaciones En esta sesión veremos algunos grupos de ellas: Clases útiles para crear y gestionar diferentes tipos de colecciones Clases para recorrer, ordenar y manipular las colecciones Clases para encapsular nuestros tipos de datos Java Colecciones - 41

42 Colecciones • En el paquete java.util
Representan grupos de objetos, llamados elementos Podemos encontrar de distintos tipos, según si sus elementos están ordenados, si permiten repetir elementos, etc La interfaz Collection define el esqueleto que deben tener todos los tipos de colecciones Por tanto, todos tendrán métodos generales como: boolean add(Object o) boolean remove(Object o) boolean contains(Object o) void clear() boolean isEmpty() Iterator iterator() int size() Object[] toArray() Java Colecciones - 42

43 Listas de elementos La interfaz List hereda de Collection
Operaciones propias de una colección tipo lista Los elementos tienen un orden (posición en la lista) Así, tendremos otros nuevos métodos, además de los de Collection: void add(int posicion, Object o) Object get(int indice) int indexOf(Object o) Object remove(int indice) Object set(int indice, Object o) Java Colecciones - 43

44 Tipos de listas ArrayList: implementa una lista de elementos mediante un array de tamaño variable NO sincronizado Vector: existe desde las primeras versiones de Java, después se acomodó al marco de colecciones implementando la interfaz List. Similar a ArrayList, pero SINCRONIZADO. Tiene métodos anteriores a la interfaz List: void addElement(Object o) / boolean removeElement(Object o) void insertElementAt(Object o, int posicion) void removeElementAt(Object o, int posicion) Object elementAt(int posicion) void setElementAt(Object o, int posicion) int size() LinkedList: lista doblemente enlazada. Útil para simular pilas o colas void addFirst(Object o) / void addLast(Object o) Object getFirst() / Object getLast() Object removeFirst() / Object removeLast() Java Colecciones - 44

45 Conjuntos Grupos de elementos donde no hay repetidos
Consideramos dos objetos de una clase iguales si su método equals los da como iguales o1.equals(o2) es true Los conjuntos se definen en la interfaz Set, que, como List, también hereda de Collection El método add definido en Collection devolvía un booleano, que en este caso permitirá saber si se insertó el elemento en el conjunto, o no (porque ya existía) Java Colecciones - 45

46 Tipos de conjuntos HashSet: los objetos del conjunto se almacenan en una tabla hash. El coste de inserción, borrado y modificación suele ser constante La iteración es más costosa, y el orden puede diferir del orden de inserción LinkedHashSet: como la anterior, pero la tabla hash tiene los elementos enlazados, lo que facilita la iteración TreeSet: guarda los elementos en un árbol El coste de las operaciones es logarítmico Java Colecciones - 46

47 Mapas No forman parte del marco de colecciones
Se definen en la interfaz Map, y sirven para relacionar un conjunto de claves (keys) con sus respectivos valores Tanto la clave como el valor pueden ser cualquier objeto Object get(Object clave) Object put(Object clave, Object valor) Object remove(Object clave) Set keySet() int size() Java Colecciones - 47

48 Tipos de mapas HashMap: Utiliza una tabla hash para almacenar los pares clave=valor. Las operaciones básicas (get y put) se harán en tiempo constante si la dispersión es adecuada La iteración es más costosa, y el orden puede diferir del orden de inserción Hashtable: como la anterior, pero SINCRONIZADA. Como Vector, está desde las primeras versiones de Java Enumeration keys() TreeMap: utiliza un árbol para implementar el mapa El coste de las operaciones es logarítmico Los elementos están ordenados ascendentemente por clave Java

49 Colecciones de tipos concretos de datos
Genéricos Colecciones de tipos concretos de datos A partir de JDK 1.5 Aseguran que se utiliza el tipo de datos correcto ArrayList<String> a = new ArrayList<String>(); a.add("Hola"); String s = a.get(0); Podemos utilizar genéricos en nuestras propias clases Java

50 Enumeraciones e iteradores
Las enumeraciones y los iteradores no son tipos de datos en sí, sino objetos útiles a la hora de recorrer diferentes tipos de colecciones Con las enumeraciones podremos recorrer secuencialmente los elementos de una colección, para sacar sus valores, modificarlos, etc Con los iteradores podremos, además de lo anterior, eliminar elementos de una colección, con los métodos que proporciona para ello. Java

51 Enumeraciones La interfaz Enumeration permite consultar secuencialmente los elementos de una colección Para recorrer secuencialmente los elementos de la colección utilizaremos su método nextElement: Object item = enum.nextElement(); Para comprobar si quedan más elementos que recorrer, utilizamos el método hasMoreElements: if (enum.hasMoreElements()) ... Java

52 Enumeraciones Con lo anterior, un bucle completo típico para recorrer una colección utilizando su enumeración de elementos sería: // Obtener la enumeracion Enumeration enum = coleccion.elements(); while (enum.hasMoreElements()) { Object item = enum.nextElement(); ...// Convertir item al objeto adecuado y // hacer con el lo que convenga } Java

53 Iteradores La interfaz Iterator permite iterar secuencialmente sobre los elementos de una colección Para recorrer secuencialmente los elementos de la colección utilizaremos su método next: Object item = iter.next(); Para comprobar si quedan más elementos que recorrer, utilizamos el método hasNext: if (iter.hasNext()) ... Para eliminar el elemento de la posición actual del iterador, utilizamos su método remove: iter.remove(); Java

54 Iteradores Con lo anterior, un bucle completo típico para recorrer una colección utilizando su iterador sería: // Obtener el iterador Iterator iter = coleccion.iterator(); while (iter.hasNext()) { Object item = iter.next(); ...// Convertir item al objeto adecuado y // hacer con el lo que convenga, por ejemplo iter.remove(); } Java

55 Bucles sin iteradores Nueva versión del for en JDK 1.5
Permite recorrer tanto arrays como colecciones Previene salirse del rango de forma segura List<String> lista = obtenerLista(); for(String cadena: lista) System.out.println (cadena); Java

56 Polimorfismo e interfaces
Hacer referencia siempre mediante la interfaz Permite cambiar la implementación sin afectar al resto del programa public class Cliente { List<Cuenta> cuentas; public Cliente() { this.cuentas = new ArrayList<Cuenta>(); } public List<Cuenta> getCuentas() { return cuentas; Java

57 Ejemplo: Algoritmos La clase Collections dispone de una serie de métodos útiles para operaciones tediosas, como ordenar una colección, hacer una búsqueda binaria, sacar su valor máximo, etc static void sort(List lista) static int binarySearch(List lista, Object objeto) static Object max(Collection col) ... Sirven para cualquier implementación de List Java

58 Comparación de objetos
Los objetos deben ser correctamente comparables para ser compatibles con las estructuras de datos y algoritmos. Comparación de igualdad: equals( ) Comparación de mayor o menor: clase Comparator o interfaz Comparable Java

59 Sobrecarga de Equals  Object.equals(Object o) public class MiClase {
... @Override public boolean equals(Object o) { // return true o false, según un criterio } Java

60 Evitar la sobrecarga de Equals si:
Cada instancia es intrínsecamente única. Por ejemplo, instancias de hilos, que representan entidades activas, y no tan sólo un conjunto de valores. Cuando no es necesaria una comparación lógica. Por ejemplo, dos números aleatorios, donde la igualdad puede ocurrir pero su comprobación no es necesaria. Una superclase ya sobrecarga equals, y el comportamiento de éste es apropiado para la clase actual. Java

61 Propiedades que debe cumplir
Simetría: para cualquier par de instancias no nulas, x.equals(y) devuelve verdadero si y sólo si y.equals(x) también devuelve verdadero. Transitividad: si x.equals(y)==true y y.equals(z)==true, entonces x.equals(z) también será verdadero, para cualesquiera instancias no nulas.

62 Sobrecargar hashCode( )
Cuando hashCode es invocado varias veces para el mismo objeto, debe devolver consistentemente el mismo entero, siempre que no se haya modificado ninguna información que afecte al resultado de equals. Esta consistencia debe mantenerse entre distintas ejecuciones de la misma aplicación. Si dos objetos son iguales según equals, entonces los métodos hashCode de ambos deben devolver el mismo entero.

63 Comparar implementando Comparable
Permite establecer un orden entre objetos Se necesita decidir qué características del objeto establecen dicho orden public class Persona implements Comparable<Persona> { public int id; public String apellido; ... @Override public int compareTo(Persona p) { return this.id - p.id; } Java

64 Comparador externo: Comparator
Puede extenderse o bien desde una clase externa, o bien desde la propia clase cuyos objetos deben ser comparados public class ComparaPersonaPorNombre implements Comparator<Persona>{ public int compare(Persona p1, Persona p2) { return p1.apellido.compareToIgnoreCase(p2.apellido); } ... List personas = new ArrayList<Persona>(); personas.add(p1); personas.add(p2); personas.add(p3); //... Collections.sort(personas); //Comparable.compareTo Collections.sort(personas, new ComparaPersonaPorNombre()); //Comparator.compare Java

65 Ejemplo: Wrappers de colecciones
Objetos que envuelven la instancia de una colección existente Implementa la misma interfaz (p.ej List) No conocemos la clase concreta del wrapper Cambia el comportamiento de algunos métodos Sincronizar acceso a la colección List Collections.synchronizedList(List l) Hacerla de sólo lectura List Collections.unmodifiableList(List l) Java

66 Wrappers Los tipos simples (int, char, float, double, etc) no pueden incluirse directamente en colecciones, ya que éstas esperan subtipos de Object en sus métodos Para poderlos incluir, se tienen unas clases auxiliares, llamadas wrappers, para cada tipo básico, que lo convierten en objeto complejo Estas clases son, respectivamente, Integer, Character, Float, Double, etc. Encapsulan al tipo simple y ofrecen métodos útiles para poder trabajar con ellos Java © Depto. Ciencia de la Computación e IA

67 Wrappers Si quisiéramos incluir un entero en un
ArrayList, lo podríamos hacer así: int a; ArrayList al = new ArrayList(); al.add(new Integer(a)); Si quisiéramos recuperar un entero de un ArrayList, lo podríamos hacer así: Integer entero = (Integer)(al.get(posicion)); int a = entero.intValue(); Java © Depto. Ciencia de la Computación e IA

68 Autoboxing Conversiones automáticas entre tipos básicos y sus wrappers
Integer n = 10; int num = n; List<Integer> lista= new ArrayList<Integer>(); lista.add(10); int elem = lista.get(0); Java © Depto. Ciencia de la Computación e IA

69 Lenguaje Java Sesión 3: Tratamiento de errores

70 Índice Excepciones Captura de excepciones Propagación de excepciones
Nested exceptions Errores en tiempo de compilación Tipos genéricos

71 Tratamiento de errores en tiempo de ejecución
Excepción: Evento que sucede durante la ejecución del programa y que hace que éste salga de su flujo normal de ejecución Se lanzan cuando sucede un error Se pueden capturar para tratar el error Son una forma elegante para tratar los errores en Java Separa el código normal del programa del código para tratar errores.

72 Jerarquía

73 Tipos de excepciones • Checked: Derivadas de Exception
Es obligatorio capturarlas o declarar que pueden ser lanzadas Se utilizan normalmente para errores que pueden ocurrir durante la ejecución de un programa, normalmente debidos a factores externos P.ej. Formato de fichero incorrecto, error leyendo disco, etc Checked: Derivadas de Exception Unchecked: Derivadas de RuntimeException Excepciones que pueden ocurrir en cualquier fragmento de código No hace falta capturarlas (es opcional) Se utilizan normalmente para errores graves en la lógica de un programa, que no deberían ocurrir P.ej. Puntero a null, fuera de los límites de un array,etc

74 Creación de excepciones
Podemos crear cualquier nueva excepción creando una clase que herede de Exception (checked), RuntimeException (unchecked) o de cualquier subclase de las anteriores. public class MiExcepcion extends Exception { public MiExcepcion (String mensaje) { super(mensaje); }

75 try-catch-finally try { // Código regular del programa
// Puede producir excepciones } catch(TipoDeExcepcion1 e1) { // Código que trata las excepciones de tipo // TipoDeExcepcion1 o subclases de ella. // Los datos sobre la excepción los encontraremos // en el objeto e1. ... } catch(TipoDeExcepcionN eN) { // TipoDeExcepcionN o subclases de ella. } finally { // Código de finalización (opcional) }

76 Ejemplos Sólo captura ArrayOutOfBoundsException
int [] hist = leeHistograma(); try { for(int i=1;;i++) hist[i] += hist[i-1]; } catch(ArrayOutOfBoundsException e) { System.out.println(“Error: “ + e.getMessage()); } Captura cualquier excepción int [] hist = leeHistograma(); try { for(int i=1;;i++) hist[i] += hist[i-1]; } catch(Exception e) { System.out.println(“Error: “ + e.getMessage()); }

77 Información sobre la excepción
Mensaje de error String msg = e.getMessage(); Traza e.printStackTrace(); Cada tipo concreto de excepción ofrece información especializada para el error que representa P.ej. ParseException ofrece el número de la línea del fichero donde ha encontrado el error

78 Lanzar una excepción • Para lanzar una excepción debemos
Crear el objeto correspondiente a la excepción Exception e = new ParseException(mensaje,linea); Lanzar la excepción con una instrucción throw throw e; Si la excepción es checked, declarar que el método puede lanzarla con throws public void leeFichero() throws ParseException { ... throw new ParseException(mensaje, linea); }

79 Capturar o propagar Si un método lanza una excepción checked deberemos Declarar que puede ser lanzada para propagarla al método llamador public void init() throws ParseException { leeFichero(); } O capturarla para que deje de propagarse try { leeFichero(); } catch(ParseException e) { System.out.println(“Error en linea “ + e.getOffset() + “: “ + e.getMessage()); } Si es unchecked Se propaga al método llamante sin declarar que puede ser lanzada Parará de propagarse cuando sea capturada Si ningún método la captura, la aplicación terminará automáticamente mostrándose la traza del error producido

80 Nested exceptions • Captura excepción causante Lanza excepción propia
try { ... } catch(IOException e) { throw new MiExcepcion("Mensaje de error", e); } Encadena errores producidos. Facilita depuración. Información detallada del error concreto. Aislar al llamador de la implementación concreta.

81 Errores en tiempo de compilación
Son preferibles a los de ejecución Errores de sintaxis: ej, falta un punto y coma, referencia a nombre de variable inexistente Errores semánticos: de más alto nivel, ej. intentar usar el valor de una variable que nunca se ha inicializado. Errores en cascada: confunden al compilador y no se localiza correctamente la causa del error. Ej, cuando falta el cierre de una llave.

82 Errores en cascada  Ejemplo:
Experto Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles Errores en cascada Ejemplo: fo ( int i = 0; i < 4; i++ ){} Prueba.java:24: '.class' expected fo ( int i = 0; i < 4; i++ ) ^ Prueba.java:24: ')' expected fo ( int i = 0; i < 4; i++ ) ^ Prueba.java:24: not a statement ^ Pueba.java:24: ';' expected ^ Prueba.java:24: unexpected type required: value : class ^ Prueba.java:24: cannot resolve symbol symbol : variable i location: class Prueba 6 errors found

83 Warnings  Ayudan a mejorar el estilo y la corrección del código 
Eclipse: permite aumentar niveles de warning

84 Herramientas de análisis
Herramientas (externas) de análisis de código fuente Detecta código duplicado, código inalcanzable, código subóptimo, expresiones complicadas, y otras posibles fuentes de bugs Plugin para Eclipse

85 Comprobación de tipos: genéricos
Experto Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles Comprobación de tipos: genéricos Antes de Java 1.5: List v = new ArrayList(); v.add("test"); Integer i = (Integer)v.get(0); // Error en tiempo de ejecución Con tipos genéricos: List<String> v = new ArrayList<String>(); v.add("test"); String s = v.get(0); // Correcto (sin necesidad de cast explícito) Integer i = v.get(0); // Error en tiempo ce compilación Java © Depto. Ciencia de la Computación e IA

86 Definición de genéricos
public class Entry<K, V> { private final K key; private final V value; public Entry(K k,V v) { key = k; value = v; } public K getKey() { return key; public V getValue() { return value; public String toString() { return "(" + key + ", " + value + ")"; Interfaces / Clases public interface List<E> { void add(E x); Iterator<E> iterator(); } public interface Iterator<E> { E next(); boolean hasNext(); Uso Entry<String, String> grade440 = new Entry<String, String>("mike", "A"); Entry<String, Integer> marks440 = new Entry<String, Integer>("mike", 100); System.out.println("grade: " + grade440); System.out.println("marks: " + marks440); }

87 Experto Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Métodos genéricos También los métodos se pueden parametrizar con tipos genéricos public static return new <T> Entry<T,T> twice(T value) { SimpleImmutableEntry<T,T>(value, value); } Entry<String, String> pair = this.<String>twice("Hello"); // Declarado String> pair = twice("Hello"); Inferido

88 Subtipos y comodines ArrayList<Hija> no es subtipo de ArrayList<Padre> Para flexibilizar el tipo podemos utilizar el comodín: <?> Para acotar el comodín en la jerarquía de herencia usamos super y extends Permitir clases derivadas: ArrayList<? extends Padre> Permitir superclases (clases padre): ArrayList<? super Padre>

89 Tipos genéricos y excepciones
Es posible indicar a un método o una clase qué excepción debe lanzar, a través de genéricos public <T extends Throwable> void metodo() throws T { throw new T(); } // O bien public class Clase<T extends Throwable> public void metodo() throws T {

90 Tipos genéricos y excepciones
No es posible es crear excepciones con tipos genéricos, debido al “borrado de tipos” Ejemplo, no se puede hacer: public class MiExcepcion<T extends Object> extends Exception { private T someObject; public MiExcepcion(T someObject) { this.someObject = someObject; } public T getSomeObject() { return someObject;

91 Borrado de tipos porque durante la compilación, tras comprobar que los tipos están bien, éstos se eliminan, el siguiente código pasa a ser: try { //Código que lanza o bien try { //Código que lanza o bien //MiExcepcion<String>, o bien //MiExcepcion<String>, o bien //MiExcepcion<Integer> //MiExcepcion<Integer> } } catch(MiExcepcion<String> ex) { // A } catch(MiExcepcion<Integer> ex) { // B catch(MiExcepcion ex) { // A } // B

92 Lenguaje Java Avanzado
Sesión 4: Serialización de datos

93 Índice Introducción a los flujos de E/S Entrada y salida estándar
Acceso a ficheros Acceso a recursos Acceso a URLs Codificación de datos Serialización de objetos

94 Flujos de E/S Las aplicaciones muchas veces necesitan enviar datos a un determinado destino o leerlos de una determinada fuente Ficheros en disco, red, memoria, otras aplicaciones, etc Esto es lo que se conoce como E/S Esta E/S en Java se hace mediante flujos (streams) Los datos se envían en serie a través del flujo Se puede trabajar de la misma forma con todos los flujos, independientemente de su fuente o destino

95 Tipos de flujos según el tipo de datos
Según el tipo de datos que transportan, distinguimos Flujos de bytes (con sufijos InputStream y OutputStream) Flujos de caracteres (con sufijos Reader y Writer) Superclases Entrada InputStream Reader Salida OutputStream Writer Bytes Caracteres

96 Tipos de flujos según su propósito
Distinguimos: Canales de datos Simplemente llevan datos de una fuente a un destino Ficheros: FileInputStream, FileReader, FileOutputStream, FileWriter Memoria: ByteArrayInputStream, CharArrayReader, ... Tuberías: PipedInputStream, PipedReader, PipedWriter, ... Flujos de procesamiento Realizan algún procesamiento con los datos Impresión: PrintWriter, PrintStream Conversores de datos: DataOutputStream, DataInputStream Bufferes: BufferedReader

97 Acceso a los flujos Todos los flujos tienen una serie de métodos básicos Flujos InputStream, Reader OutputStream, Writer Métodos read, reset, close write, flush, close Los flujos de procesamiento Se construyen a partir de flujos canales de datos Los extienden proporcionando métodos de más alto nivel, p.ej: Flujos BufferedReader DataOutputStream PrintStream, PrintWriter Métodos readLine writeInt, writeUTF,... print, println

98 Objetos de la E/S estándar
En Java también podemos acceder a la entrada, salida y salida de error estándar Accedemos a esta E/S mediante flujos Estos flujos se encuentran como propiedades estáticas de la clase System Tipo de flujo InputStream Propiedad System.in Entrada Salida Salida de error PrintStream System.out PrintStream System.err

99 Salida estándar La salida estándar se ofrece como flujo de procesamiento PrintStream Con un OutputStream a bajo nivel sería demasiado incómoda la escritura Este flujo ofrece los métodos print y println que permiten imprimir cualquier tipo de datos básico En la salida estándar System.out.println(“Hola mundo”); En la salida de error System.err.println(“Error”);

100 Flujos de ficheros • Canales de datos para acceder a ficheros Entrada
Experto Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles Flujos de ficheros Canales de datos para acceder a ficheros Entrada FileReader Salida FileWriter Caracteres Binarios FileInputStream FileOutputStream Se puede acceder a bajo nivel directamente de la misma forma que para cualquier flujo Podemos construir sobre ellos flujos de procesamiento para facilitar el acceso de estos flujos

101 Lectura y escritura de ficheros
Experto Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles Lectura y escritura de ficheros public void copia_fichero() { int c; try { FileReader in = new FileReader("fuente.txt"); FileWriter out = new FileWriter("destino.txt"); while( (c = in.read()) != -1) { out.write(c); } in.close(); out.close(); } catch(FileNotFoundException e1) { System.err.println("Error: No se encuentra el fichero"); } catch(IOException e2) { System.err.println("Error leyendo/escribiendo fichero");

102 Uso de flujos de procesamiento
public void escribe_fichero() { FileWriter out = null; PrintWriter p_out = null; try { out = new FileWriter("result.txt"); p_out = new PrintWriter(out); p_out.println("Este texto será escrito en el fichero"); } catch(IOException e) { System.err.println("Error al escribir en el fichero"); } finally { p_out.close(); }

103 Sistema de ficheros La clase File contiene utilidades para trabajar con el sistema de ficheros Constantes para indicar los separadores de directorios (‘/’ ó ‘\’) Hace las aplicaciones independientes de la plataforma Crear, borrar o renombrar ficheros y directorios Listar los ficheros de un directorio Comprobar y establecer los permisos sobre ficheros Obtener la ruta de un fichero Obtener datos sobre ficheros (tamaño, fecha, etc) Etc...

104 Acceso a recursos Los recursos incluidos en un JAR no se encuentran directamente en el sistema de ficheros No podremos utilizar los objetos anteriores para acceder a ellos Accedemos a un recurso en el JAR con getClass().getResourceAsStream(“/datos.txt”); Anteponiendo ‘/’ se busca de forma relativa al raíz del JAR Si no, buscará de forma relativa al directorio correspondiente al paquete de la clase actual

105 URLs URL = Uniform Resource Locator Se compone de
Cadena para localizar los recursos en Internet Se compone de protocolo://servidor[:puerto]/recurso P.ej. Se conecta al servidor A través del puerto por defecto (puerto 80) Utilizando protocolo HTTP para comunicarse Solicita el recurso /es/index.html

106 URLs en Java Se encapsulan en la clase URL
URL url = new URL(" Es obligatorio especificar el protocolo P.ej. es una URL mal formada Si la URL está mal formada se producirá una excepción MalformedURLException try { URL url = new URL(" } catch(MalformedURLException e) { System.err.println("Error: URL mal construida"); }

107 Lectura del contenido Podemos leer el contenido de la URL abriendo un flujo de entrada con InputStream in = url.openStream(); Leeremos de este flujo de la misma forma que con cualquier otro flujo Con los métodos a bajo nivel (byte a byte) O utilizando un flujo de procesamiento P.ej, si la URL corresponde a un documento HTML obtendremos el código fuente de este documento

108 Codificación Podemos codificar de forma sencilla los datos para enviarlos a través de un flujo de bytes (en serie) Utilizaremos un flujo DataOutputStream String nombre = "Jose"; int edad = 25; ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeUTF(nombre); dos.writeInt(edad); dos.close(); baos.close();

109 Experto Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles
Descodificación Para descodificar estos datos del flujo realizaremos el proceso inverso Utilizamos un flujo DataInputStream ByteArrayInputStream bais = new ByteArrayInputStream(datos); DataInputStream dis = new DataInputStream(bais); String nombre = dis.readUTF(); int edad = dis.readInt(); dis.close(); bais.close();

110 Entrada/Salida de objetos
Experto Universitario en Desarrollo de Aplicaciones para Dispositivos Móviles Entrada/Salida de objetos Si queremos enviar un objeto a través de un flujo deberemos convertirlo a una secuencia de bytes Esto es lo que se conoce como serialización Java serializa automáticamente los objetos Obtiene una codificación del objeto en forma de array de bytes En este array se almacenarán los valores actuales de todos los campos del objeto serializado Java © Depto. Ciencia de la Computación e IA

111 Objetos serializables
Para que un objeto sea serializable debe cumplir: 1. Implementar la interfaz Serializable public MiClase implements Serializable { ... } Esta interfaz no obliga a definir ningún método, sólo marca el objeto como serializable 1. Todos los campos deben ser Datos elementales o Objetos serializables

112 Flujos de objetos Para enviar o recibir objetos tendremos los flujos de procesamiento ObjectInputStream ObjectOutputStream Estos flujos proporcionan respectivamente los métodos readObject writeObject Con los que escribir o leer objetos del flujo Utilizan la serialización de Java para codificarlos y descodificarlos

113 Lenguaje Java Sesión 5: Hilos

114 Índice Creación de hilos y ciclo de vida Sincronización de hilos
Bloques vigilados Interbloqueos Interfaz Lock Variables atómicas y colecciones Ejecutores y pools

115 Hilos  Cada hilo es un flujo de ejecución independiente
Tiene su propio contador de programa Todos acceden al mismo espacio de memoria Necesidad de sincronizar cuando se accede concurrentemente a los recursos Existen estructuras de datos sincronizadas (ej, Vector) y sin sincronizar (ej, ArrayList)

116 Creación de Hilos  Se pueden crear de dos formas:
Heredando de Thread Problema: No hay herencia múltiple en Java Implementando Runnable Debemos crear sólo los hilos necesarios Dar respuesta a más de un evento simultáneamente Permitir que la aplicación responda mientras está ocupada Aprovechar máquinas con varios procesadores

117 Heredar de Thread  Heredar de Thread y sobrecargar run( ) 
public class MiHilo extends Thread { public void run() { // Codigo de la tarea a ejecutar en el hilo } Heredar de Thread y sobrecargar run( ) Instanciar el hilo Thread t = new Thread(new MiHilo()); t.start();

118 Implementar Runnable  Implementar Runnable  Instanciar el hilo
public class MiHilo implements Runnable { public void run() { // Codigo de la tarea a ejecutar en el hilo } Implementar Runnable Instanciar el hilo Thread t = new Thread(new MiHilo()); t.start();

119 Ciclo de vida de los hilos
El hilo será no ejecutable cuando: Se encuentre durmiendo (llamando a sleep) Se encuentre bloqueado (con wait) Se encuentre bloqueado en una petición de E/S

120 Scheduler El scheduler decide qué hilo ejecutable ocupa el procesador en cada instante Se sacará un hilo del procesador cuando: Se fuerce la salida (llamando a yield) Un hilo de mayor prioridad se haga ejecutable Se agote el quantum del hilo Establecemos la prioridad con t.setPriority(prioridad); La prioridad es un valor entero entre Thread.MIN_PRIORITY y Thread.MAX_PRIORITY

121 Concurrencia y sección crítica
Cuando varios hilos acceden a un mismo recurso pueden producirse problemas de concurrencia Sección crítica: Trozo del código que puede producir problemas de concurrencia Debemos sincronizar el acceso a estos recursos Este código no debe ser ejecutado por más de un hilo simultáneamente Todo objeto Java (Object) tiene una variable cerrojo que se utiliza para indicar si ya hay un hilo en la sección crítica Los bloques de código synchronized utilizarán este cerrojo para evitar que los ejecute más de un hilo

122 Bloques sincronizados
Para sincronizar un bloque de código podemos indicarle el objeto cuyo cerrojo utilizaremos. El cerrojo (lock) se adquiere al inicio de la sección crítica y se libera al final de ésta Otro hilo no podrá adquirir ese mismo cerrojo al mismo tiempo synchronized(algun_objeto) { // Código sección crítica }

123 Métodos sincronizados
Sincronzar un método o una sección de código public synchronized void seccion_critica() { // Codigo } Se utiliza el cerrojo del objeto en el que se definen (cerrojo implícito) Se podrán ejecutar por un sólo hilo en un instante dado.

124 Uso de la sincronización
Deberemos utilizar la sincronización sólo cuando sea necesario, ya que reduce la eficiencia No sincronizar métodos que contienen un gran número de operaciones que no necesitan sincronización Reorganizar en varios métodos No sincronizar clases que proporcionen datos fundamentales Dejar que el usuario decida cuando sincronizarlas en sus propias clases

125 Sincronización reentrante
La sincronización en Java es “reentrante” porque un lock puede ser adquirido varias veces por un mismo hilo. Es decir, en el mismo hilo, una sección sincronizada puede contener a otra y esto no produce un bloqueo a pesar de que las dos adquieren el lock del objeto this: class Reentrant { public synchronized void a() { b(); System.out.println(" estoy en a() "); } public synchronized void b() { System.out.println(" estoy en b() ");

126 Dependencia de hilos Podemos esperar a que un hilo haya acabado de ejecutarse para poder continuar otro hilo Para ello bloquearemos el hilo actual que debe esperar a otro hilo t con: t.join();

127 Bloqueo de hilos Si el hilo va a esperar a que suceda un evento (por ejemplo, terminar una E/S), hay que bloquearlo para que no ocupe el procesador: wait(); Cuando suceda el evento debemos desbloquearlo desde otro hilo con: notify(); Ambos métodos deben ser invocados desde métodos sincronizados

128 wait(); // desocupa la CPU
Bloques vigilados En lugar de esperar iterativamente (que ocupa la CPU): public void bloqueVigilado() { // No hacerlo así! while(!condicion) {} // Se detiene aquí, //comprobando iterativamente la condición System.out.println("La condición se ha cumplido"); } Bloquear el hilo y esperar una notificación por parte de otro. public synchronized bloqueVigilado() { while(!condicion) { try { wait(); // desocupa la CPU } catch (InterruptedException e) {} } System.out.println("La condición se ha cumplido");

129 Ejemplo: productor/consumidor
El productor produce si el buffer no está lleno, y si no debe esperar El consumidor consume si el buffer no está vacío, y si no debe esperar

130 Productor import java.util.Random;
public class Producer implements Runnable { private Drop drop; public Producer(Drop drop) { this.drop = drop; } public void run() { String importantInfo[] = { "Mares eat oats", "Does eat oats", "Little lambs eat ivy", "A kid will eat ivy too" }; Random random = new Random(); for (int i = 0; i < importantInfo.length; i++) { drop.put(importantInfo[i]); try { Thread.sleep(random.nextInt(5000)); } catch (InterruptedException e) {} drop.put("DONE");

131 Consumidor import java.util.Random;
public class Producer implements Runnable { private Drop drop; public Producer(Drop drop) { this.drop = drop; } public void run() { String importantInfo[] = { "Mares eat oats", "Does eat oats", "Little lambs eat ivy", "A kid will eat ivy too" }; Random random = new Random(); for (int i = 0; i < importantInfo.length; i++) { drop.put(importantInfo[i]); try { Thread.sleep(random.nextInt(5000)); } catch (InterruptedException e) {} drop.put("DONE");

132 Recurso // ... public synchronized void put(String message) {
// Wait until message has // been retrieved. while (!empty) { try { wait(); } catch (InterruptedException e) {} } // Toggle status. empty = false; // Store message. this.message = message; // Notify consumer that status // has changed. notifyAll(); Recurso public class Drop { // Message sent from producer // to consumer. private String message; // True if consumer should wait // for producer to send message, // false if producer should wait for // consumer to retrieve message. private boolean empty = true; public synchronized String take() { // Wait until message is // available. while (empty) { try { wait(); } catch (InterruptedException e) {} } // Toggle status. empty = true; // Notify producer that // status has changed. notifyAll(); return message; // ... } //Main class: public class ProducerConsumerExample { public static void main(String[] args) { Drop drop = new Drop(); (new Thread(new Producer(drop))).start(); (new Thread(new Consumer(drop))).start(); }

133 Interbloqueos Deadlock: hilo A queda a la espera de que B lo desbloquee, a la vez que B queda a la espera de que A lo desbloquee: se interbloquean sin usar CPU Livelock: hilo A realiza acción que causa que B realice otra acción que a su vez vuelve a causar la acción de A: se interbloquean ocupando la CPU Stravation (inanición): otros hilos “hambrientos” ocupan el recurso (o CPU) que nuestro hilo necesita para seguir funcionando

134 Mecanismos de alto nivel
Implementaciones que proporciona Java para facilitar la programación con concurrencia Interfaz Lock Colecciones concurrentes Variables atómicas Ejecutores y pools Otros muchos en el paquete java.util.concurrent

135 La interfaz Lock En lugar de synchronized: 
synchronized(this){ // acceder al recurso } Adquirir un objeto Lock y después liberarlo Lock l = ...; l.lock(); try { // acceder al recurso protegido por l } finally { l.unlock();

136 La interfaz Lock  Añade algunos métodos más versátiles
tryLock( ) : rechaza darnos el lock si éste no está disponible en el instante o bien tras un tiempo de espera especificado. Permite evitar deadlocks. lockInterruptibly( ) : rechaza darnos el lock si otro hilo envía una interrupción antes de que el lock haya sido adquirido Da soporte a un mecanismo de wait/notify a través de objetos Condition que dejarían el hilo a la espera de que se cumpla la condición

137 Lock y Condition class BufferLimitado {
final Lock lock = new ReentrantLock(); //Dos condiciones para notificar sólo a los hilos //que deban hacer put o take, respectivamente final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); final Object[] items = new Object[100]; int putptr, takeptr, count; public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == items.length) notFull.await(); items[putptr] = x; if (++putptr == items.length) putptr = 0; ++count; notEmpty.signal(); } finally { lock.unlock(); } public Object take() throws InterruptedException { lock.lock(); while (count == 0) notEmpty.await(); Object x = items[takeptr]; if (++takeptr == items.length) takeptr = 0; --count; notFull.signal(); return x; Lock y Condition }

138 Colecciones concurrentes
La colección Vector garantiza el acceso sincronizado El paquete java.util.concurrent contiene colecciones con un soporte más avanzado para concurrencia BlockingQueue: FIFO con tiempo de espera máximo cuando añadimos y no cabe, o quitamos y no hay. ConcurrentMap: subinterfaz de Map que define operaciones atómicas útiles (quitar una clave valor sólo si la clave está presente, etc). ConcurrentNavigableMap para coincidencias aproximadas

139 Variables atómicas Para no tener que sincronizar el acceso a variables, contamos con versiones atómicas de éstas: AtomicBoolean AtomicInteger AtomicIntegerArray AtomicIntegerFieldUpdater<T> AtomicLong AtomicLongArray AtomicLongFieldUpdater<T> AtomicMarkableReference<V> AtomicReference<V> AtomicReferenceArray<E> AtomicReferenceFieldUpdater<T,V> AtomicStampedReference<V>

140 Variables atómicas Ejemplo: synchronized / variable atómica
class ContadorSincronizado { private int c = 0; import java.util.concurrent.atomic.AtomicInteger; class ContadorAtomic { private AtomicInteger c = new AtomicInteger(0); public synchronized void increment() { c++; } public void increment() { c.incrementAndGet(); } public synchronized void decrement() { c--; } public void decrement() { c.decrementAndGet(); } public synchronized int value() { return c; } public int value() { return c.get(); } } }

141 Ejecutores Se separa la gestión de la ejecución de los hilos en clases especializadas Interfaz Executor: obliga a implementar el método execute(Runnable r) En lugar de iniciar el hilo con (new Thread(r)).start( ); lo iniciaremos con e.execute(r); teniendo: Runnable r; Executor e;

142 ExecutorService  Subinterfaz de Executor
Añade el método Future submit( objeto ) que acepta objetos Runnable y Callable, que permiten devolver un valor al finalizar la tarea. submit( ) devuelve objetos Future que permiten obtener el estado de la tarea a ejecutar y devuelven un resultado en el caso de Callable.

143 ScheduledExecutorService
Subinterfaz de ExecutorService Añade el método schedule( ) que ejecuta un Runnable o Callable después de un tiempo especificado También añade scheduleAtFixedRate( ) y scheduleWithFixedDelay( ) para tareas periódicas

144 Pools de hilos Uno o varios “worker thread” ejecutan los métodos run( ) de distintos Runnable / Callable, pero en el mismo hilo. Se ahorra la sobrecarga de creación y destrucción de hilos en la que interviene reserva y liberación de memoria Creación del pool – distintas maneras: Método estático newFixedThreadPool(n) Instancia de ThreadPoolExecutor o de ScheduledThreadPoolExecutor.

145 Instancia de ThreadPoolExecutor
//Al principio del fichero: //import java.util.concurrent.*; //import java.util.*; //Poner a ejecutar dos tareas y una que quedará en cola: for(int i=0; i<3; i++){ threadPool.execute(task); System.out.println("Tareas:" + queue.size()); } int poolSize = 2; int maxPoolSize = 2; long keepAliveTime = 10; //Encolar otra tarea más que declaramos aquí mismo: threadPool.execute( new Runnable() { public void run() { for (int i = 0; i < 10; i++) { try { System.out.println("i = " + i); Thread.sleep(1000); } catch (InterruptedException ie){ } } }); final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(5); ThreadPoolExecutor threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, queue); Runnable myTasks[3] = ....; // y le asignamos tareas //Ejecuta las tareas que queden pero ya no acepta nuevas: threadPool.shutdown();

146 Sobrecarga de ThreadPoolExecutor
class PausableThreadPoolExecutor extends ThreadPoolExecutor { //Método nuevo: public void pause() { pauseLock.lock(); //Sección sincronizada try { isPaused = true; } finally { pauseLock.unlock(); } private boolean isPaused; private ReentrantLock pauseLock = new ReentrantLock(); private Condition unpaused = pauseLock.newCondition(); //Sobrecargamos el método: protected void beforeExecute(Thread t, Runnable r) { super.beforeExecute(t, r); pauseLock.lock(); //Sección sincronizada try { while (isPaused) unpaused.await(); //Bloquearlo } catch (InterruptedException ie) { t.interrupt(); } finally { pauseLock.unlock(); } //Método nuevo: public void resume() { pauseLock.lock(); //Sección sincronizada try { isPaused = false; unpaused.signalAll(); //Desbloquea hilos bloqueados } finally { pauseLock.unlock(); } } //Nota: para pausar cada hilo el programador debe //implementar la lógica necesaria

147 Lenguaje Java FIN


Descargar ppt "Sesión 1: Introducción al Lenguaje Java"

Presentaciones similares


Anuncios Google