Publicado el 5 de Octubre del 2020
419 visualizaciones desde el 5 de Octubre del 2020
3,2 MB
30 paginas
Creado hace 13a (09/05/2011)
Federico Peinado
www.federicopeinado.es
Depto. de Ingeniería del Software e
Inteligencia Artificial
disia.fdi.ucm.es
Facultad de Informática
www.fdi.ucm.es
Universidad Complutense de Madrid
www.ucm.es
La ejecución de tareas en paralelo optimiza la
utilización de los recursos del sistema
• Ejemplo: cuando un proceso está esperando la finalización
de una operación de E/S, otros procesos pueden aprovechar
el procesador del sistema que en ese momento no se usa
Las máquinas actuales pueden ejecutar varios
programas simultáneamente
• En teoría: sólo tantos como procesadores (núcleos) tengan
• En la práctica: intercalando la ejecución de varios procesos,
cambiando muy rápido entre ellos, “parece” como si se
ejecutaran simultáneamente (programación concurrente)
La programación paralela/concurrente es mucho
más compleja que la convencional
Laboratorio de Programación de Sistemas – Hilos y sincronización
2
Son las unidades básicas de ejecución de la programación
concurrente
Procesos
• Disponen de su propio espacio de memoria
• Se pueden comunicar a través de pipes y sockets
Hilos (threads, también llamados hebras)
• Ejecuciones simultáneas dentro de un mismo proceso (podemos
considerarlos como “procesos ligeros”)
• Su espacio de memoria es, por tanto, compartido
Java pone más énfasis en los hilos que en los procesos
• La propia máquina virtual de Java es un único proceso con
múltiples hilos
• Java 6 sí propone nuevos mecanismos de control de procesos,
que no vamos a estudiar aquí…
Laboratorio de Programación de Sistemas – Hilos y sincronización
3
Laboratorio de Programación de Sistemas – Hilos y sincronización
4
Cuando se inicia un programa en Java, la
máquina virtual crea un hilo principal
• El hilo se encargará de invocar al método main de
la clase que se comienza a ejecutar
• El hilo termina cuando se acaba de ejecutar el
método main
• Si el hilo principal crea otros hilos, éstos
comenzarán su ejecución de forma concurrente
• Sólo cuando no queda ningún hilo activo, es
cuando se termina el programa
Laboratorio de Programación de Sistemas – Hilos y sincronización
5
La clase principal para conseguir
concurrencia en Java es la clase Thread
• Dispone de un método start() que ocasiona la
ejecución del código que tenga dentro de su
método run() en un nuevo hilo
Todos los hilos se ejecutan en la misma
máquina virtual (mismo proceso)
• Por tanto comparten recursos, como la memoria
• En realidad sólo puede haber un hilo ejecutándose
a la vez (se alternan, gracias a la concurrencia)
Laboratorio de Programación de Sistemas – Hilos y sincronización
6
Esquema general
• Se implementar el método run, cuyo código define
lo que va a hacer el hilo durante su ejecución
• Se crear el hilo y se llama a su método start, que se
encarga, entre otras cosas, de llamar a run
Dos alternativas posibles para la creación
Implementando la interfaz Runnable
1.
2. Heredando de la clase Thread
Laboratorio de Programación de Sistemas – Hilos y sincronización
7
public class HelloRunnable implements Runnable {
System.out.println("Hello from a thread!");
public void run() {
}
public static void main(String args[]) {
}
(new Thread(new HelloRunnable())).start();
}
Lo más recomendable para aplicaciones de tamaño medio-grande
• Es más flexible y permite combinar este interfaz con lo que heredemos de
cualquier otra clase
• Permite gestión de hilos de alto nivel mediante el API de Java:
java.util.concurrent
Laboratorio de Programación de Sistemas – Hilos y sincronización
8
System.out.println("Hello from a thread!");
public void run() {
}
public static void main(String args[]) {
}
(new HelloThread()).start();
public class HelloThread extends Thread {
}
Lo más cómodo para aplicaciones simples, al resultar
ligeramente más sencillo que lo anterior
Laboratorio de Programación de Sistemas – Hilos y sincronización
9
Laboratorio de Programación de Sistemas – Hilos y sincronización
10
El planificador de la máquina virtual de Java
(MVJ) decide qué hilo ejecutar en cada momento
• La especificación no hace explícito el algoritmo a utilizar
Hay cuestiones dependientes de la implementación
• La creación de un hilo en el S.O. subyacente
• La simulación de los hilos dentro de la MVJ
Sí es obligatorio que el planificador tenga en
cuenta las prioridades de los hilos
• Si hay varios hilos con la misma prioridad, todos se deben
ejecutar en algún momento
• No es obligatorio que deban ejecutarse hilos de menor
prioridad si hay pendientes algunos con mayor prioridad
Laboratorio de Programación de Sistemas – Hilos y sincronización
11
La clase Thread tiene dos métodos para trabajar
para cambiarla
con las prioridades
• setPriority(int) establece la prioridad del hilo. Puede
generar una excepción si:
El parámetro es inválido, o
El hilo que invoca al método no tiene los permisos necesarios
• getPriority() devuelve la prioridad del hilo
constantes estáticas en la clase Thread
• MAX_PRIORITY (=10): prioridad máxima
• MIN_PRIORITY (=1): prioridad mínima
• NORM_PRIORITY (=5): prioridad por defecto.
Para los valores de las prioridades, existen tres
Laboratorio de Programación de Sistemas – Hilos y sincronización
12
Tanto Swing como AWT crean un hilo nuevo
• Sirve para procesar los eventos de entrada (teclado y ratón)
Consecuencias
• Es problemático leer de teclado desde el hilo principal con Swing
lanzado: dos hilos leen simultáneamente del mismo dispositivo
• Cuando hay eventos, el hilo de Swing es quien invoca los métodos
de usuario de procesado de eventos
Para que la interacción con el usuario sea fluida, el hilo
de Swing tiene prioridad 6, y los hilos normales 5
• Cuando hay un evento de entrada, responde inmediatamente
• Cuando no hay eventos, el hilo está suspendido a la espera de los
mismos para no perjudicar a los otros hilos
Laboratorio de Programación de Sistemas – Hilos y sincronización
13
Si la gestión del evento (hilo de Swing) lleva mucho
tiempo, el resto de los eventos no se procesan
• ¡La ventana parece no reaccionar a las órdenes del usuario!
Evitar crear métodos largos de gestión de eventos
• Bloquean el funcionamiento de la GUI hasta que terminan
Si el procesado de un evento va a durar demasiado,
el gestor debería:
1. Recopilar toda la información de los componentes Swing
adecuados
2. Crear un nuevo hilo que realice la tarea en paralelo
Laboratorio de Programación de Sistemas – Hilos y sincronización
14
Laboratorio de Programación de Sistemas – Hilos y sincronización
15
void sleep(long t) duerme el hilo durante al menos t
milisegundos
• Cuando transcurran, el hilo estará preparado para ejecutarse
• El planificador lo lanzará cuando considere oportuno
void sleep(long milis, int nanos) versión con más
precisión (a nivel de nanosegundos)
• En la práctica, las implementaciones no tienen tanta precisión…
InterruptedException que hay que capturar
Las dos versiones del método sleep pueden generar la excepción
void yield() pausa temporalmente el hilo
• No queda suspendido, sino que sigue estando preparado para la
ejecución
• El planificador se activa y carga otro hilo para ejecutar, que podría ser el
mismo
Laboratorio de Programación de Sistemas – Hilos y sincronización
16
¡No se puede parar la ejecución de un hilo desde fuera!
• En realidad sí, pero se desaconseja (métodos obsoletos)…
Para parar un hilo de ejecución, tenemos que solicitárselo
mediante interrupt(), y confiar en que nos hará caso
El hilo debería comprobar periódicamente si lo quieren
parar
• Algunos métodos de la librería de Java generan una excepción si
durante su ejecución se les intenta interrumpir (como es el caso
de sleep())
• Así se comprueba si nos han mandado una interrupción:
Thread.interrupted()
• Así se comprueba si otro hilo ha recibido una interrupción:
isInterrupted()
Laboratorio de Programación de Sistemas – Hilos y sincronización
17
// Hilo que presenta un mensaje importante cada 4 segundos
public class HiloObediente1 implements Runnable {
// ...
public void run() {
for (int i = 0; i < importantInfo.length; i++) {
// Paramos 4 segundos
try {Thread.sleep(4000);
} catch (InterruptedException e) {
}// Escribimos el mensaje
System.out.println(importantInfo[i]);
// Nos han pedido terminar. Obedecemos
return;
}}// ...
}
Laboratorio de Programación de Sistemas – Hilos y sincronización
18
// Hilo que multiplica 10000 matrices de 1000x1000
public class HiloObediente2 extends Runnable {
// ...
void run() {
}}
// ...
}
for (int i = 0; i < 10000; i++) {
this.multiplicaMatriz(i);
if (Thread.interrupted())
// Nos han pedido que acabemos...
break; // o return;
Laboratorio de Programación de Sistemas – Hilos y sincronización
19
Esperar la ejecución de un hilo t para
continuar la ejecución
•t.join()
Comprobar si un hilo está activo
•t.isAlive()
Laboratorio de Programación de Sistemas – Hilos y sincronización
20
Laboratorio de Programación de Sistemas – Hilos y sincronización
21
El hecho de que varios hilos compartan el
mismo espacio de memoria puede causar dos
problemas
1.
2.
Interferencias
Inconsistencias
Algunos hilos necesitan esperar a otros para
disponer de datos importantes o evitar
problemas de acceso simultáneo a recursos
• Java proporciona mecanismos de sincronización de
hilos para tratar estos problemas
Laboratorio de Programación de Sistemas – Hilos y sincronización
22
Proporcionan exclusión mutua para acceder a un recurso
Uso de synchronized al declarar un método
compartido
public synchronized void metodo()
• No es posible ejecutar simultáneamente dos métodos
sincronizados del mismo objeto
Sincronizando todo, se pierde la ventaja de la
concurrencia… pero se puede sincronizar únicamente
la parte del código del método que interesa:
public void addName(String nam
Comentarios de: LPS: Hilos y sincronización (0)
No hay comentarios