Tema 6. Threads: programas multitarea
Tema 6. Threads: programas multitarea
Tema 6. Threads: programas multitarea
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