Programación concurrente
Java y Servicios Web I
Master en Ingeniería Matemática
Manuel Montenegro
Dpto. Sistemas Informáticos y Computación
Desp. 467 (Mat)
[email protected]
Programación concurrente
● Consiste en la ejecución simultánea de varias
tareas, que pueden interactuar entre sí.
● Paso de mensajes.
● Acceso a memoria compartida.
● Un hilo (thread) es una tarea (conjunto de
instrucciones) que puede ejecutarse en paralelo
con las demás.
● Estos hilos pueden ser todos ejecutados por un sólo
procesador, o distribuidos entre los distintos
procesadores.
● La asignación de hilos a procesadores es realizada por el
sistema operativo.
29/Mayo/2012
9. Programación concurrente
2
Contenidos
● Operaciones con hilos
● Acceso a memoria compartida
● Condiciones de carrera
● Secciones críticas
● Multitarea con Swing
29/Mayo/2012
9. Programación concurrente
3
Creación de hilos
● Para crear un hilo, se deberá crear una clase
que implemente la interfaz Runnable.
public interface Runnable {
void run();
}
● La clase ha de tener un método run(), que
realizará las acciones correspondientes.
29/Mayo/2012
9. Programación concurrente
4
Creación de hilos
● Para definir las acciones que se realizan en un
hilo, se deberá crear una clase que implemente
la interfaz Runnable.
public interface Runnable {
void run();
}
● La clase ha de tener un método run(), que
realizará las acciones correspondientes.
29/Mayo/2012
9. Programación concurrente
5
Ejemplo
public class Enanito implements Runnable {
private String nombre;
public Enanito(String nombre) {
this.nombre = nombre;
}
public void run() {
for (int contador = 1; contador <= 10; contador++) {
System.out.printf("%s cuenta hasta %d\n", nombre, contador);
}
System.out.printf("%s terminó\n", nombre);
}
}
29/Mayo/2012
9. Programación concurrente
6
Creación de hilos
● El método tradicional de creación de hilos
consiste en crear una instancia de la clase
Thread, y pasarle el objeto Runnable
correspondiente mediante su constructor.
● A continuación se debe llamar al método
start() del objeto thread correspondiente
para iniciar su ejecución.
29/Mayo/2012
9. Programación concurrente
7
Ejemplo
public class Test1 {
public static void main(String[] args) {
String[] nombres = {"Sabio", "Gruñón", "Mudito",
"Dormilón", "Tímido", "Tontín", "Bonachón"};
for (String nomb : nombres) {
Enanito e = new Enanito(nomb);
Thread t = new Thread(e);
t.start();
}
}
}
29/Mayo/2012
9. Programación concurrente
8
Ejemplo
29/Mayo/2012
9. Programación concurrente
9
Creación de hilos
● Desde la versión 5 de Java, no es necesario crear
objetos de la clase Thread directamente.
● Existe un objeto ExecutorService (paquete
java.util.concurrent) que recibe las tareas a
ejecutar (objetos que implementan Runnable) y las
distribuye en distintos hilos.
● Existen varios tipos de ExecutorService
● Implementan distintas políticas de distribución de tareas
en hilos.
● Un ExecutorService no tiene constructor. Se crea
mediante métodos estáticos contenidos en la clase
Executors.
29/Mayo/2012
9. Programación concurrente
10
Ejemplo
public class Test2 {
public static void main(String[] args) {
String[] nombres = {"Sabio", "Gruñón", "Mudito",
"Dormilón", "Tímido", "Tontín", "Bonachón"};
ExecutorService exec = Executors.newCachedThreadPool();
for (String n : nombres) {
Enanito e = new Enanito(n);
exec.execute(e);
}
exec.shutdown();
}
}
No admitir más tareas en el Executor
29/Mayo/2012
9. Programación concurrente
11
Tipos de ExecutorService
● CachedThreadPool
● Genera tantos hilos como considere necesarios.
● Procura reciclar los hilos cuya tarea ha terminado.
● FixedThreadPool
● Crea, al inicio, una cantidad de hilos fija.
● SingleThreadExecutor
● Como un FixedThreadPool, pero con un único hilo.
● Si se envían varias tareas a un
SingleThreadExecutor, se pondrán en cola.
29/Mayo/2012
9. Programación concurrente
12
Dormir un hilo
public class Enanito implements Runnable {
…
public void run() {
for (int contador = 1; contador <= 10; contador++) {
System.out.printf("%s cuenta hasta %d\n", nombre, contador);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
System.out.println("Se ha interrumpido");
}
}
System.out.printf("%s terminó\n", nombre);
}
}
Detener hilo 1 seg.
29/Mayo/2012
9. Programación concurrente
13
Prioridad de hilos
public class Enanito implements Runnable {
…
public void run() {
if (nombre.equals("Acaparadorcito")) {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
} else {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
}
for (int contador = 1; contador <= 10; contador++) {
System.out.printf("%s cuenta hasta %d\n", nombre, contador);
}
System.out.printf("%s terminó\n", nombre);
}
}
29/Mayo/2012
9. Programación concurrente
14
Prioridad de hilos
public class Test2 {
public static void main(String[] args) {
String[] nombres = {"Sabio", “Acaparadorcito”, "Gruñón", "Mudito",
"Dormilón", "Tímido", "Tontín", "Bonachón"};
ExecutorService exec = Executors.newCachedThreadPool();
for (String n : nombres) {
Enanito e = new Enanito(n);
exec.execute(e);
}
exec.shutdown();
}
}
29/Mayo/2012
9. Programación concurrente
15
Esperar la finalización de un hilo
● El método awaitTermination de
ExecutorService permite detener el hilo que
ejecuta dicho método hasta que los hilos del
servicio ejecutor terminen.
● Recibe como parámetro una cantidad de
tiempo máximo a esperar, cuya unidad de
medida es el segundo parámetro.
● Lanza una excepción InterruptedException si
el la espera se interrumpe externamente.
29/Mayo/2012
9. Programación concurrente
16
Esperar la finalización de un hilo
public class Test2 {
public static void main(String[] args) {
String[] nombres = {"Sabio", "Gruñón", "Mudito",
"Dormilón", "Tímido", "Tontín", "Bonachón"};
ExecutorService exec = Executors.newCachedThreadPool();
for (String n : nombres) {
Enanito e = new Enanito(n);
exec.execute(e);
}
exec.shutdown();
try {
exec.awaitTermination(100, TimeUnit.SECONDS);
System.out.println("Los siete enanitos han terminado");
} catch(InterruptedException e) {
System.out.println("Se interrumpió");
}
}
}
29/Mayo/2012
9. Programación concurrente
17
Contenidos
● Operaciones con hilos
● Acceso a memoria compartida
● Condiciones de carrera
● Secciones críticas
● Multitarea con Swing
29/Mayo/2012
9. Programación concurrente
18
Acceso a memoria compartida
● Supongamos que ahora los hilos manipulan
una zona de memoria común.
public class Contador {
private int valor;
public Contador() { valor = 0; }
public void incrementar() { valor++; }
public int getValor() { return valor; }
}
29/Mayo/2012
9. Programación concurrente
19
Acceso a memoria compartida
public class Enanito implements Runnable {
private String nombre;
private Contador contador;
public Enanito(String nombre, Contador contador) {
this.nombre = nombre;
this.contador = contador;
}
public void run() {
for (int i = 0; i < 1000; i++)
contador.incrementar();
}
}
Cada enanito incrementa el
contador 1000 veces
29/Mayo/2012
9. Programación concurrente
20
Acceso a memoria compartida
public class Test2 {
public static void main(String[] args) {
String[] nombres = {"Sabio", "Gruñón", "Mudito",
"Dormilón", "Tímido", "Tontín", "Bonachón"};
Contador c = new Contador();
ExecutorService exec = Executors.newCachedThreadPool();
for (String n : nombres) {
Enanito e = new Enanito(n, c);
exec.execute(e);
}
exec.shutdown();
try {
exec.awaitTermination(100, TimeUnit.SECONDS);
System.out.println("Los siete enanitos han terminado");
} catch(InterruptedException e) {
System.out.println("Se interrumpió");
}
System.out.printf("El valor final del contador es: %d\n", c.getValor());
}
}
el mismo contador
Todos los enanitos incrementan
29/Mayo/2012
9. Programación concurrente
21
Acceso a memoria compartida
● El valor final del contador debería ser 7000.
● Sin embargo:
29/Mayo/2012
9. Programación concurrente
22
Condiciones de carrera
contador = 0
T2
T1
…
…
contador++
…
…
29/Mayo/2012
9. Programación concurrente
23
Condiciones de carrera
contador = 0
T2
T1
…
…
LOAD contador
ADD 1
STORE contador
…
…
29/Mayo/2012
9. Programación concurrente
24
Condiciones de carrera
contador = 0
T2
Registro = 0
T1
…
…
LOAD contador
ADD 1
STORE contador
…
…
29/Mayo/2012
9. Programación concurrente
25
Condiciones de carrera
contador = 0
T2
Registro = 1
T1
…
…
LOAD contador
ADD 1
STORE contador
…
…
29/Mayo/2012
9. Programación concurrente
26
Condiciones de carrera
contador = 1
T2
Registro = 1
T1
…
…
LOAD contador
ADD 1
STORE contador
…
…
29/Mayo/2012
9. Programación concurrente
27
Condiciones de carrera
contador = 1
T2
Registro = 1
T1
…
…
LOAD contador
ADD 1
STORE contador
…
…
29/Mayo/2012
9. Programación concurrente
28
Condiciones de carrera
cont
Comentarios de: Programación corrurrente - Java y Servicios Web (0)
No hay comentarios