Vous êtes sur la page 1sur 35

Multitarea en Java

Rafa Caballero - UCM

Programa Monoproceso (monotarea)


En cada momento hay una nica instruccin ejecutndose Se dice que el programa es monotarea, o monoproceso o monohebra (o single threading).

Programa multiproceso

En algn punto el programa se divide en varios procesos (threads) que se ejecutan (aparentemente) de manera simultnea Programa multiproceso, multitarea, multihebra (o multithreading)

Para qu?

Programas que tengan que realizar varias tareas de manera simultnea Programas en los que la ejecucin de una parte requiera tiempo y no deba detener el resto del programa

Para qu ? Ejemplo 1
Programa que controla sensores en una fbrica: Los procesos que se encargan de controlar sensores diferentes son independientes y los sensores deben controlarse de manera simultnea
Temperatura Combustible

Programa
Presin

Tiempo

Rafa Caballero - U

Para qu? Ejemplo 2


Durante la impresin de un documento (tarea que puede tomar tiempo) el programa puede y debe continuar ejecutndose.

Programa

Multitarea en Java
Idea: Definir clases especiales para las tareas que requieran ejecutarse en una hebra de ejecucin (thread) separada Estas clases deben incluir la funcin especial public void run(), equivalente a main() pero para hebras Los objetos de la clase sern inicializados desde otra clase con el mtodo start()

Clase para multitarea

2 Mtodos:
n

Mediante herencia (extensin) de la clase java.lang.Thread Mediante la implementacin del interfaz java.lang.Runnable

Rafa Caballero - U

Ejemplo: extensin de Thread

El programa ir escribiendo dos sucesiones ascendentes de nmeros simultneamente Una hebra por cada contador

Ejemplo: Contadores (Versin 1)


class Contador extends Thread { private int inicio,fin; // valor inicial y final del contador private String nombre; // nombre de la hebra // constructor con los valores iniciales y final y el nombre public Contador(int desde, int hasta, String id) { inicio = desde; fin = hasta; nombre = id; } // funcin principal public void run() { System.out.println(nombre+ " empieza..."); for (int i = inicio; i <= fin; i++) { System.out.print (nombre+" dice: "+i + ". "); try{ sleep(10); // paramos una centesima de segundo } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(nombre + " acaba."); }

Rafa Caballero - U

Ejemplo: Contadores (Versin 1)


// clase principal: esta clase inicializara las hebras public class principal { static public void main(String[] args) { // al declararlas NO comienzan Contador hebraA = new Contador(1, 10, "HebraA"); Contador hebraB = new Contador(20, 30, "HebraB"); System.out.println("Vamos a iniciar las dos hebras"); // ahora comienzan hebraA.start(); hebraB.start(); System.out.println("Hebras inicializadas"); // hacemos un poco de tiempo antes de despedirnos for (int i=0; i<50000000; i++) ; System.out.println("Programa principal terminado"); } } // principal

Ejemplo: contadores
Una ejecucin del programa: Vamos a iniciar las dos hebras Hebras inicializadas HebraA empieza... HebraA dice: 1. HebraB empieza... HebraB dice: 20. HebraA dice: 2. HebraB dice: 21. HebraA dice: 3. HebraB dice: 22. HebraA dice: 4. Programa principal terminado HebraB dice: 23. HebraA dice: 5. HebraB dice: 24. HebraA dice: 6. HebraB dice: 25. HebraA dice: 7. HebraB dice: 26. HebraA dice: 8. HebraB dice: 27. HebraA dice: 9. HebraB dice: 28. HebraA dice: 10. HebraB dice: 29. HebraA acaba. HebraB dice: 30. HebraB acaba.

Ejemplo: contadores
Vamos a iniciar las dos hebras Hebras Inicializadas HebraA empieza HebraA dice:1 HebraA dice:2 HebraA dice:3 HebraA dice:4 HebraA dice:5 HebraA dice:6 HebraA dice:7 HebraA dice:8 HebraA dice:9 HebraA dice:10 HebraA acaba Programa Principal Terminado Hebra B empieza HebraB dice: 20 HebraB dice: 21 HebraB dice: 22 HebraB dice: 23 HebraB dice: 24 HebraB dice: 25 HebraB dice: 26 HebraB dice: 27 HebraB dice: 28 HebraB dice: 29 HebraB acaba

Ejemplo: Interfaz Runnable


Se utiliza generalmente cuando la clase ya hereda de otra clase y por tanto no puede heredar de Thread class Hebra extends loquesea implements Runnable { }

Rafa Caballero - U

Ejemplo: Contadores (versin 2)


class Contador implements Runnable { private int inicio,fin; // valor inicial y final del contador private String nombre; // nombre de la hebra // constructor con los valores iniciales y final y el nombre public Contador(int desde, int hasta, String id) { inicio = desde; fin = hasta; nombre = id; } public void run() { System.out.println(nombre+ " empieza..."); for (int i = inicio; i <= fin; i++) { System.out.print (nombre+" dice: "+i + ". "); try{ Thread.sleep(10); // paramos una centesima de segundo } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(nombre + " acaba."); }

Rafa Caballero - U

Ejemplo: Contadores (versin 2)


// clase principal: esta clase inicializara las hebras public class principal { static public void main(String[] args) { // al declararlas NO comienzan Thread hebraA = new Thread (new Contador(1, 10, "HebraA")); Contador hebraA = new Contador(1, 10, "HebraA"); Thread hebraB = new (new Contador(20, 30, "HebraB")); Contador hebraB = Thread new Contador(20, 30, "HebraB"); // ahora comienzan hebraA.start(); hebraB.start(); System.out.println("Hebras inicializadas"); // hacemos un poco de tiempo antes de despedirnos for (int i=0; i<50000000; i++) ; System.out.println("Programa principal terminado"); } } // principal

Comunicacin entre hebras


La forma de comunicarse consiste usualmente en compartir un mismo objeto Generalmente el objeto se pasa como parmetro en la constructora de la clase hebra

Ejemplo: Juego para adivinar un nmero

rbitro
Nmero: 5 2 7

Jugador

Rafa Caballero - U

Ejemplo: Juego para adivinar un nmero

3 Clases:
Principal: Inicializa el rbitro y lanza las hebras de los jugadores n rbitro: Contiene el nmero a adivinar, el turno y muestra el resultado n Jugador: Extiende Thread e incluye al rbitro.
n

Rafa Caballero - U

Ejemplo: Juego para adivinar un nmero


public class Principal { public static void main(String[] args) { // creamos el rbitro y los jugadores Arbitro arbitro = new Arbitro(3); // 3 jugadores Jugador j1 = new Jugador(1,arbitro); Jugador j2 = new Jugador(2,arbitro); Jugador j3 = new Jugador(3,arbitro); // ponemos a los jugadores en marcha j1.start(); j2.start(); j3.start(); } }

Rafa Caballero - U

Ejemplo: Juego para adivinar un nmero


class Arbitro { private int totalJugadores; // nm. de jugadores private int turno; // a quin le toca private int numero; // nmero a adivinar private boolean acabo; // true cuando se haya terminado el juego public Arbitro(int nJugadores) {// constructora totalJugadores = nJugadores; turno = 1+(int) (totalJugadores*Math.random()); numero = 1+(int) (10*Math.random()); // nmero entre 1 y 10 acabo = false; } public int toca() { return turno; } public boolean seAcabo() { return acabo; } public synchronized void nuevaJugada(int jugador, int suNumero) {} }

Rafa Caballero - U

Ejemplo: Juego para adivinar un nmero


public synchronized void nuevaJugada(int jugador, int suNumero){ if (jugador == toca()) { // ha acertado System.out.println(Jugador+jugador+" dice: "+suNumero); if (suNumero == numero) { System.out.println(Jugador +jugador + " gana!!!"); acabo = true; } else // ha fallado. ver a quien le toca ahora if (turno == totalJugadores) turno = 1; else turno++; } else System.out.println(jugador+" trata de hacer trampa!"); }

Ejemplo: Juego para adivinar un nmero


class Jugador extends Thread { Arbitro arbitro; int identificador; public Jugador( int elId,Arbitro elArbitro) { arbitro = elArbitro; identificador = elId; } public void run() { while (arbitro.seAcabo() == false) { // hasta el fin del juego if (arbitro.toca()==identificador) { // es nuestro turno int jugada = 1+(int) (10*Math.random()); arbitro.nuevaJugada(identificador,jugada); } // if } // while } // run }

Ejemplo: Juego para adivinar un nmero


Una ejecucin del programa:
Jugador 3 dice: 9 Jugador 1 dice: 2 Jugador 2 dice: 6 Jugador 3 dice: 7 Jugador 1 dice: 2 Jugador 2 dice: 5 Jugador 2 gana!!!

Rafa Caballero - U

Ejemplo: Juego para adivinar un nmero


Observaciones:
n

Aunque cada hebra tenga su variable rbitro todas son referencias al mismo objeto Con synchronized se protegen aquellas funciones que no se quiera que se puedan interrumpir por otra hebra

Ejercicio: Control de stock


Se sabe que a un almacn llegan piezas cada 8 horas. La cantidad de piezas oscila cada vez entre 400 y 1000 Del almacn salen cada 24 horas piezas hacia la fbrica, a un ritmo de entre 2000 y 2500 piezas (todas a la vez) El almacn parte de 8000 piezas y tiene una capacidad mxima de 20000 piezas
Rafa Caballero

Ejercicio: Control de stock


El programa debe simular este proceso parando si:
n

Llega un nuevo cargamento y ya no cabe en el almacn La fbrica necesita piezas pero no hay suficientes piezas en el almacn

Rafa Caballero - U

Ejercicio: Control de stock

Ejercicio: Control de stock


Vamos a hacer la simulacin con 4 clases:
n

Retirada: Simula retirada de piezas hacia la fbrica. Adems escribe el nmero de das transcurridos desde el comienzo Envo: Simula el envo de piezas al almacn Almacn: Simula el almacn. Tendr funciones para atender las llegadas y las salidas de piezas. Controlar si hay algn error y mostrar mensajes con el movimiento del almacn Principal: Funcin main que pondr en marcha la aplicacin

n n

Rafa Caballero - U

Ejercicio: Control de stock


Envo y Retirada heredarn de la clase Thread y compartirn el objeto tipo Almacn. Ambas pararn cuando el Almacn indique que hay un error (bien porque no hay piezas para atender un pedido o porque no caben ms piezas y hay un envo)

Rafa Caballero - U

Ejercicio: Control de stock


Para simular el tiempo, las funciones run() de las clases Retirada y Envio incluirn sendas llamadas a sleep:
n

En el caso de Retirada: try{ sleep(2400); // simulacin de un da } catch (InterruptedException e) { e.printStackTrace(); } En el caso de Envio: try{ sleep(800); // simulacin de 8 horas } catch (InterruptedException e) { e.printStackTrace(); }

De est manera habr 3 envos por cada retirada

Rafa Caballero - U

Ejercicio: Control de stock


// Estructura de la clase almacn: class Almacen { private final int maximo=20000; // capacidad del almacn private int stock = 8000; // nm. Piezas en el almacn. Al principio 8000 private boolean hayError = false; // al principio no hay error // Mtodo entrada: carga es la cantidad de piezas que llegan al almacn // si la carga + el stock superan el maximo mostrar un mensaje de error y // pondr hayError a true. En otro caso incrementar el stock con la carga public void entrada(int carga) { .} // Mtodo salida: piezas es la cantidad de piezas pedida por la fbrica // Si stock < piezas se mostrar un mensaje de erro y se pondr // hayError a true. En otro caso se decrementar el stock en piezas public void salida(int piezas) { } // pedido public boolean error() { return hayError; } }

Rafa Caballero - U

Ejercicio: Control de stock


Da 1 Pedido de 2179 piezas Hay 5821 piezas en el almacn Llegan 744 piezas Hay 6565 piezas en el almacn Llegan 580 piezas Hay 7145 piezas en el almacn Llegan 624 piezas Hay 7769 piezas en el almacn
... Da 41 Pedido de 2409 piezas Hay 699 piezas en el almacn Llegan 586 piezas Hay 1285 piezas en el almacn Llegan 404 piezas Hay 1689 piezas en el almacn Llegan 462 piezas Hay 2151 piezas en el almacn

Da 2 Pedido de 2420 piezas Da 42 Hay 5349 piezas en el almacn Pedido de 2483 piezas

No hay piezas suficientes!

Ejercicio: Control de stock


Resultados de 20 simulaciones
80 70 60 50 40 30 20 10 0 1 4 7 10 13 16 19 Das hasta quedarse vaco

Rafa Caballero - U

Ejercicio: Control de stock

Sugerencia: probar con otros valores Por ejemplo, con 4 envos por da se comprobar que el almacn se llena en aproximadamente 25 das

Vous aimerez peut-être aussi