11.05.2013 Views

Tema 6. Threads: programas multitarea

Tema 6. Threads: programas multitarea

Tema 6. Threads: programas multitarea

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>Tema</strong> <strong>6.</strong> <strong>Threads</strong>: <strong>programas</strong><br />

<strong>multitarea</strong><br />

Procesos e hilos<br />

Creación de threads<br />

Ciclo de vida de un thread<br />

Sincronización<br />

Prioridades<br />

Grupos de threads<br />

Relación de métodos<br />

Ejemplo sincronización<br />

1


Procesos e hilos<br />

Programa <strong>multitarea</strong>:<br />

Realización “simultánea” de 2 o más<br />

actividades<br />

Proceso:<br />

Es un programa en ejecución<br />

Posee su propia memoria<br />

Thread o hilo:<br />

Flujo de ejecución dentro de un<br />

proceso<br />

Un proceso puede tener varios<br />

hilos en ejecución<br />

Proceso<br />

<strong>Threads</strong><br />

2


Creación de <strong>Threads</strong><br />

Opción 1<br />

Crear una clase derivada de la clase<br />

java.lang.Thread<br />

Sobrecargar el método run()<br />

Opción 2<br />

Declarar una clase que implemente la interface<br />

java.lang.Runnable<br />

Definir el método run()<br />

Crear un objeto de tipo Thread pasándole al<br />

constructor el objeto de la nueva clase<br />

3


Creación de un hilo derivando<br />

de la clase Thread<br />

class Hilo1 extends Thread<br />

{<br />

public Hilo1(String str)<br />

{<br />

super(str);<br />

}<br />

public void run()<br />

{<br />

for(int i=0;i


Creación de un hilo implementando<br />

la interface Runnable<br />

class Hilo2 implements Runnable<br />

{<br />

String nombreThread;<br />

public Hilo2(String str)<br />

{<br />

nombreThread = str;<br />

}<br />

public void run()<br />

{<br />

for(int i=0;i


Ciclo de vida de un Thread<br />

6


Ejecución de un nuevo Thread<br />

La creación de un Thread no implica su<br />

ejecución<br />

Hay que inicializarlo con el método start()<br />

El método start() llama al método run()<br />

Después de ejecutar start(), el thread está<br />

en estado ejecutable (runnable)<br />

No quiere decir que se esté ejecutando en todo<br />

momento, ya que debe compartir la CPU con el<br />

resto de threads en estado runnable<br />

7


Detención temporal (i)<br />

Los tiempos de CPU que el sistema asigna a<br />

los threads en estado runnable se emplean<br />

en ejecutar el método run() de cada thread<br />

Un thread puede renunciar a su tiempo de<br />

CPU y otorgárselo al sistema para asignárselo<br />

a otro thread → método yield()<br />

Si ningún thread requiere la CPU para una<br />

actividad intensiva, el sistema volverá asignar<br />

nuevo tiempo al thread generoso<br />

8


Detención temporal (ii)<br />

Formas de parar un thread (not runnable):<br />

Ejecutando el método sleep() → detiene el thread el<br />

tiempo establecido. Suele llamarse desde el método run()<br />

Mediante el método wait() → detiene el thread hasta que<br />

se ejecuten los métodos notify() o notifyAll()<br />

Cuando el thread está esperando realizar operaciones de<br />

E/S<br />

Cuando el thread está intentando llamar a un método<br />

syncronized de un objeto, y el objeto está bloqueado por<br />

otro thread<br />

El thread pasa a estado runnable cuando cese<br />

alguna de las condiciones anteriores<br />

La clase Thread dispone de los métodos stop() y<br />

suspend(), pero su uso se desaconseja<br />

9


Detención temporal (iii)<br />

Forma preferible de detener un thread: utilización<br />

conjunta de los métodos wait() y notifyAll()<br />

Modos de llamar a wait()<br />

1)<br />

Indicando el tiempo máximo que debe estar parado<br />

Si se ejecuta notify() o notifyAll(), que indican la<br />

liberación de los objetos bloqueados, el thread continuará<br />

sin esperar a concluir el tiempo<br />

2)<br />

Sin argumentos<br />

El thread permanece parado hasta reinicializarlo con los<br />

métodos notify() o notifyAll()<br />

Los métodos wait() y notify() deben estar incluidos<br />

en un método synchronized<br />

10


Sincronización<br />

Se utiliza cuando:<br />

2 o más threads intentan acceder al mismo recurso al<br />

mismo tiempo<br />

Un thread debe esperar a que estén listos los datos que le<br />

debe suministrar otro thread<br />

Los métodos que accedan a un recurso compartido<br />

deben declararse como synchronized<br />

Ej: public synchronized void metodoSincronizado()<br />

Si el método accede a un recurso, Java bloquea el recurso,<br />

de forma que el resto de threads no pueden acceder al<br />

mismo hasta que el primero finalice su tarea<br />

Bloquear un recurso u objeto:<br />

Sobre el objeto no pueden actuar 2 métodos sincronizados<br />

al mismo tiempo<br />

11


Niveles de bloqueo<br />

A nivel de objetos<br />

Se declaran todos los métodos de la clase como<br />

synchronized<br />

Al ejecutar un método sobre un objeto, el sistema bloquea<br />

dicho objeto, permaneciendo a la espera cualquier thread<br />

que intente ejecutar algún método sincronizado del mismo<br />

objeto<br />

Si hay varios objetos, es posible tener distintos threads<br />

ejecutando métodos sobre diversos objetos<br />

A nivel de clases<br />

Se corresponde con los métodos de clase o static, y por<br />

tanto con las variables de clase o static<br />

12


Prioridades<br />

Es posible establecer prioridades en los threads para<br />

repartir el tiempo de la CPU<br />

Las prioridades vienen definidas por variables<br />

miembro (de tipo entero) de la clase Thread.<br />

Constantes asociadas a prioridades:<br />

MAX_PRIORITY: máxima prioridad<br />

MIN_PRIORITY: mínima prioridad<br />

NORM_PRIORITY: prioridad por defecto<br />

Métodos:<br />

Para modificar la prioridad → método setPriority()<br />

Para obtener su prioridad → método getPriority()<br />

13


Grupos de threads (i)<br />

Un hilo debe pertenecer a un grupo de hilos<br />

(ThreadGroup)<br />

Los grupos de threads permiten manejar múltiples threads como<br />

un solo objeto<br />

Por defecto cuando se crea un thread pertenece al<br />

ThreadGroup del thread desde el que ha sido creado.<br />

Si no se crea ningún ThreadGroup, pertenecerá al<br />

ThreadGroup llamado main, que se crea al arrancar el programa<br />

Para que un thread pertenezca a un grupo, hay que<br />

indicarlo al crearlo:<br />

Thread (ThreadGroup grupo, Runnable destino)<br />

Thread (ThreadGroup grupo, String nombre)<br />

Thread (ThreadGroup grupo, Runnable destino, String nombre)<br />

14


Grupos de threads (ii)<br />

Un ThreadGroup debe pertenecer a otro ThreadGroup<br />

Si no se especifica ninguno, pertenecerá al ThreadGroup<br />

desde el que ha sido creado (por defecto el main)<br />

Constructores de ThreadGroup:<br />

ThreadGroup(ThreadGroup parent, String nombre);<br />

ThreadGroup(String name); → toma como parent el<br />

ThreadGroup al cual pertenece el thread desde el que se<br />

crea<br />

Ejemplo:<br />

ThreadGroup miThreadGroup = new ThreadGroup(“mi grupo”);<br />

Thread miThread = new Thread(miThreadGroup, “hilo de mi grupo”);<br />

15


Relación de métodos (1)<br />

Clase Thread<br />

Métodos estáticos<br />

Thread currentThread(): Devuelve la tarea que se está<br />

ejecutando<br />

void yield(): Cede el control a otra tarea de la misma<br />

prioridad<br />

void sleep (long): Duerme la tarea los ms especificados<br />

Métodos de instancia<br />

void start(): Comienza la ejecución del Thread<br />

void run(): Cuerpo de la tarea<br />

void setPriority(int): Asigna la prioridad<br />

int getPriority(): Devuelve la prioridad<br />

void setName(String): Asigna un nombre<br />

String getName(): Devuelve el nombre<br />

16


Relación de métodos (2)<br />

Clase Object<br />

Métodos para sincronización<br />

public final void wait()<br />

El thread actual espera hasta que otro thread<br />

utilice notify() o nofityAll()<br />

public final void notify()<br />

Despierta a un único thread que estuviera<br />

esperando<br />

Si hay varios, lo elige arbitrariamente<br />

public final void notifyAll()<br />

Despierta a todos los threads que estuvieran<br />

esperando<br />

17


Ejemplo sincronización (1)<br />

HiloEscritor valor<br />

HiloLector<br />

Funcionamiento:<br />

Dato<br />

int obtener() void asignar(int)<br />

- El escritor escribe 5 datos<br />

- El lector lee 5 datos<br />

- Se debe leer cada dato escrito<br />

18


Ejemplo sincronización (2)<br />

public class EjSincronizar<br />

{<br />

public static void main(String[] args)<br />

{<br />

Dato d = new Dato();<br />

HiloEscritor esc=new HiloEscritor(d);<br />

HiloLector lec=new HiloLector(d);<br />

}<br />

}<br />

esc.start();<br />

lec.start();<br />

19


Ejemplo sincronización (3)<br />

class HiloLector extends Thread<br />

{<br />

private Dato dato;<br />

}<br />

public HiloLector(Dato d)<br />

{<br />

dato = d;<br />

}<br />

public void run()<br />

{<br />

int valor;<br />

for(int i=0;i


Ejemplo sincronización (4)<br />

class HiloEscritor extends Thread<br />

{<br />

private Dato dato;<br />

}<br />

public HiloEscritor(Dato d)<br />

{<br />

dato = d;<br />

}<br />

public void run()<br />

{<br />

int valor;<br />

for(int i=0;i


Ejemplo sincronización (5)<br />

class Dato<br />

{<br />

private boolean disponible;<br />

private int valor;<br />

}<br />

public Dato()<br />

{<br />

disponible = false;<br />

}<br />

public synchronized int obtener()<br />

{<br />

}<br />

public synchronized void asignar(int v)<br />

{<br />

}<br />

22


Ejemplo sincronización (6)<br />

public synchronized int obtener()<br />

{<br />

while(disponible==false){<br />

try{<br />

wait();<br />

}<br />

catch(InterruptedException e){}<br />

}<br />

disponible = false;<br />

System.out.println("Leyendo: " +valor);<br />

notifyAll();<br />

return valor;<br />

}<br />

23


Ejemplo sincronización (7)<br />

public synchronized void asignar(int v)<br />

{<br />

while(disponible==true){<br />

try{<br />

wait();<br />

}<br />

catch(InterruptedException e){}<br />

}<br />

valor = v;<br />

System.out.println("Escribiendo: " +valor);<br />

disponible = true;<br />

notifyAll();<br />

}<br />

24

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!