Está en la página 1de 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).

Rafa Caballero - UCM


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)

Rafa Caballero - UCM


Rafa Caballero - UCM

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 - UCM
Rafa Caballero - UCM

Para qu? Ejemplo 2

Durante la impresin de un documento (tarea


que puede tomar tiempo) el programa puede
y debe continuar ejecutndose.

Programa
Rafa Caballero - UCM

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

n Mediante la implementacin del interfaz


java.lang.Runnable
Rafa Caballero - UCM
Rafa Caballero - UCM

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 - UCM

}
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
Rafa Caballero - UCM
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.

Rafa Caballero - UCM


Rafa Caballero - UCM

Ejemplo: contadores
Vamos a iniciar las dos hebras
Hebras Inicializadas

HebraA empieza Hebra B empieza


HebraA dice:1 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 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 - UCM


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 - UCM
}
Ejemplo: Contadores (versin 2)
// clase principal: esta clase inicializara las hebras
public class principal {
static public void main(String[] args) {
// al declararlas NO comienzan
Contador
Thread hebraA
hebraA = new
= new ThreadContador(1, 10, "HebraA");
(new Contador(1, 10, "HebraA"));
Contador
Thread hebraB
hebraB = Thread
= new new Contador(20, 30, "HebraB");
(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

Rafa Caballero - UCM


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

Rafa Caballero - UCM


Ejemplo: Juego para adivinar un nmero

3
4
rbitro
Nmero: 5

2 7

Jugador Rafa Caballero - UCM


Ejemplo: Juego para adivinar un nmero

3 Clases:
n 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.

Rafa Caballero - UCM


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 - UCM
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 - UCM
Rafa Caballero - UCM

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!");
}
Rafa Caballero - UCM

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 - UCM


Ejemplo: Juego para adivinar un nmero

Observaciones:

n Aunque cada hebra tenga su variable rbitro


todas son referencias al mismo objeto

n Con synchronized se protegen aquellas funciones


que no se quiera que se puedan interrumpir por
otra hebra

Rafa Caballero - UCM


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 - UCM
Ejercicio: Control de stock

El programa debe simular este proceso


parando si:

n Llega un nuevo cargamento y ya no cabe en el


almacn

n La fbrica necesita piezas pero no hay


suficientes piezas en el almacn
Rafa Caballero - UCM
Rafa Caballero - UCM

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

n Envo: Simula el envo de piezas al almacn

n 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

n Principal: Funcin main que pondr en marcha la aplicacin

Rafa Caballero - UCM


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 - UCM


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(); }

n 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 - UCM


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 - UCM
Ejercicio: Control de stock
Da 1
Pedido de 2179 piezas
...
Hay 5821 piezas en el almacn Da 41
Llegan 744 piezas Pedido de 2409 piezas
Hay 6565 piezas en el almacn Hay 699 piezas en el almacn
Llegan 580 piezas Llegan 586 piezas
Hay 7145 piezas en el almacn Hay 1285 piezas en el almacn
Llegan 624 piezas Llegan 404 piezas
Hay 7769 piezas en el almacn 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!

Rafa Caballero - UCM


Ejercicio: Control de stock

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

Rafa Caballero - UCM


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

Rafa Caballero - UCM

También podría gustarte