CENTRO UNIVERSITARIO UA E M TEXCOCO INGENIERÍA EN COMPUTACIÓN
Paradigmas de Programación II
HILOS, THREADS: Una Introducción a la concurrencia en Java Irene Aguilar
HILOS
Irene Aguilar Juárez
Necesidad de dividir un programa en subtareas que se ejecuten de manera independiente pero coordinada. Un hilo es un flujo de control que se ejecuta dentro de un proceso, compartiendo cierta información del estado del proceso. Un proceso = 1 o más hilos de ejecución Cada hilo tiene la impresión de tener la C P U para él, pero en realidad se reparte entre todos los hilos (monoprocesador).
2
CONCURRENCIA EN JVM Proporciona mecanismos de sincronización
Creación/destrucción de hilos Exclusión mútua (sincronización) comunicación
java.lang.Thread
Irene Aguilar Juárez
3
CREACIÓN DE HILOS
Thread unHilo = new Thread(); public class OtroHilo extends Thread{...} Forma más fácil/rápida de crear un hilo
public class OtroHiloMas implements Runnable {...} Por si debe extender otra clase, sólo obliga a implementar run()
Irene Aguilar Juárez
4
CREACIÓN DE HILOS public class SimpleThread extends Thread { private int countDown = 5; private static int threadCount = 0; private int threadNumber = ++threadCount;
Sobrecargar método Thread
public void run() { while(true) { System.out.println("Thread " + threadNumber + "(" + countDown + ")"); if(--countDown == 0) return; } } public static void main(String[] args) { for(int i = 0; i < 5; i++) new SimpleThread().start(); System.out.println("All Threads Started"); }
public SimpleThread() { System.out.println("Making " + threadNumber); }
Extender la clase Thread
Start(): construir obj., Config. Hilo y llamar a run()
} Irene Aguilar Juárez
5
CLASE THREAD Métodos de control: Crear un thread (constructor Thread).
Métodos de consulta y modificación de propiedades:
Iniciar la ejecución (start).
Reanudar la ejecución (resume). Ceder el procesador (yield). Esperar la terminación de otro thread (join). Irene Aguilar Juárez
Detener la ejecución (suspend, interrupt, stop, sleep).
Nombre (getName / setName). Prioridad (getPriority / setPriority): MIN_PRIORITY (1). NORM_PRIORITY (5), MAX_PRIORITY (10).
Grupo de hilos (getThreadGroup): Cada thread pertenece a un grupo. Daemon (isDaemon / setDaemon): Indica si el thread es daemon o no.
6
ESTADOS DE UN HILO yield()
runnable
new
run()
interrupt() return dead
sleep() wait()
notify() notifyAll() bloqued
Irene Aguilar Juárez
7
ESTADOS DE UN HILO
Irene Aguilar Juárez
8
New: objeto creado pero no ha sido iniciada su ejecución. Runnable: se puede ejecutar cuando sea planificado para utilizar la CPU. Puede o no estar ejecutándose, y no hay razón para que no se ejecute. Dead: desaparición del hilo, normalmente como efecto de retornar del método run(). Blocked: el hilo podría ejecutarse pero existe algo que lo impide. El planificador no lo tendrá en cuenta hasta que vuelva al estado Runnable.
CLASE THREAD ⚫ Planificación
⚫ Política de planificación: Por prioridad y con apropiación. ⚫ La prioridad es estática: El algoritmo de planificación no modifica la prioridad de los threads. ⚫ Se aplica round robin para 2 threads con igual prioridad.
⚫ Sincronización ⚫ La sincronización entre threads se ofrece a través de los métodos wait, notify y notifyAll, heredados de la clase java.lang.Object. 9 Irene Aguilar Juárez
SINCRONIZACIÓN
10 Irene Aguilar Juárez
Evitar condiciones de carrera Bloquear el acceso a secciones críticas Todos los objetos tienen un bloqueo asociado (monitor) Adquirir el bloqueo de un objeto impide que cualquier otro hilo adquiera ese bloqueo hasta que sea liberado por el hilo que lo posee. Métodos y sentencias synchronized
MONITORES JAVA Entrada (espera)
acceso exclusivo
Espera
entrar
Propietario
liberar
adquirir hilo
liberar y salir
11 Irene Aguilar Juárez
MÉTODOS SYNCHRONIZED Declarar métodos con sección crítica como synchronized:
public synchronized sumar(int x){ saldo+=x; } public synchronized restar(int x){ saldo-=x; }
12 Irene Aguilar Juárez
MÉTODOS SYNCHRONIZED ⚫ Al invocar a un método sincronizado sobre un objeto 1. se adquiere el bloqueo del objeto 2. se ejecuta el cuerpo del método 3. se libera el bloqueo (automáticamente)
⚫ la posesión de los bloqueos es por hilo, invocar un método sincronizado desde otro método también sincronizado no bloquea ⚫ el bloqueo se libera cuando se retorna del método sincronizado más externo 13 Irene Aguilar Juárez
⚫ Se impide que un hilo se bloquee por un bloqueo que ya posee (invocaciones recursivas):
SENTENCIAS SYNCHRONIZED Permiten adquirir el bloqueo de cualquier objeto, no sólo del objeto actual Para ámbitos menores que un método
synchronized (expresRefenciaAUnObjeto){ sentencias; }
Permite mantener el bloqueo únicamente el tiempo imprescindible.
14 Irene Aguilar Juárez
SENTENCIAS SYNCHRONIZED class SumarYRestar{ Object bloqueoSaldo = new Object(); int saldo=0;
public sumar(){ int x = obtenerValor(); synchronized (bloqueoSaldo){ saldo += x;} } public restar(){....} } 15 Irene Aguilar Juárez
COMUNICACIÓN ENTRE HILOS synchronized permite el bloqueo entre hilos, pero también ha de haber comunicación entre ellos. wait(): deja al hilo esperando por una condición, liberando el bloqueo sobre el objeto (op. atómica)
synchronized void siCondicion(){ while (!condicion) wait(); // hacer cuando se cumpla la condicion ... }
siempre en un bucle
Irene Aguilar Juárez
16
COMUNICACIÓN ENTRE HILOS notify(), notifyAll(): indican a los hilos en espera que la condición puede haberse cumplido
synchronized void cambiarCondicion(){ // se altera algún valor de la condición notifyAll(); // o notify(); }
notifyAll() despierta a todos los hilos esperando, notify() selecciona sólo a uno para ser despertado todos los hilos esperan por la misma condición sólo un hilo como mucho se puede beneficiar
Irene Aguilar Juárez
17
PLANIFICACIÓN DE HILOS Cada hilo tiene una prioridad asociada Inicialmente recibe la prioridad del hilo que lo crea
Thread.MIN_PRIORITY, Thread.NORM_PRIORITY, Thread.MAX_PRIORITY getPriority(), setPriority()
Replanificación voluntaria: Espera limitada sleep(long milis) sleep(long milis, int nanos) Cesión del turno yield()
Irene Aguilar Juárez
18
FINALIZACIÓN Una vez que se un hilo ha empezado a ejecutarse, está vivo: isAlive() retorna true. Un hilo continua hasta que termina:
el método run() retorna normalmente el método run() finaliza bruscamente se invoca un destroy() sobre el hilo: para el hilo en seco sin liberar los bloqueos.
Cancelación: Thread.interrup() isInterrupted() interrupt()
Irene Aguilar Juárez
19
VOLATILE
• Java garantiza que la lectura o escritura de cualquier variable (no long ni double) es atómica. • El acceso atómico no garantiza que se lea el valor escrito más recientemente. • La sincronización no siempre es necesaria (un escritor, muchos lectores) • Volatile indica al compilador que el valor del campo podrá cambiar en cualquier momento, e impide las suposiciones del compilador sobre ese campo. 20 Irene Aguilar Juárez
ESPERANDO A UN HILO Un hilo puede esperar a que otro finalice hiloAlQueEsperar.join()
21 Irene Aguilar Juárez