Вы находитесь на странице: 1из 14

Lenguaje de Programación JAVA – 2º IINF y 2º ITIG

Lenguaje JAVA

11. Threads

300

11. Threads
La máquina virtual Java implementa un entorno que permite
a varias secuencias de instrucciones ejecutarse al mismo
tiempo. Estas secuencias se llaman threads.
La capacidad de tener varios threads o hilos de ejecución
ejecutándose simultáneamente se llama concurrencia.

David Contreras Bárcena 301

David Contreras Bárcena - ETSI


Lenguaje de Programación JAVA – 2º IINF y 2º ITIG
Lenguaje JAVA

11. Threads - Concurrencia


Los threads no se ejecutan verdaderamente al mismo
tiempo. En realidad, el interpretador Java ejecuta los threads
uno tras otro (restricción impuesta por todo sistema
monoprocesador). Esto responde a la política empleada por
el planificador del Sistema Operativo.

Thread
Thread Ejecución...
Ejecución... Espera
Esperadel
del Ejecución...
Ejecución...
AA procesador
procesador

Thread
Thread Espera
Esperadel
del Ejecución...
Ejecución... Espera
Esperadel
del
BB procesador
procesador procesador
procesador

tiempo

David Contreras Bárcena 302

11. Threads - Ciclo de vida

Definición new Thread()

Bloqueado Muerto

sleep() notify()
wait()
stop()

sleep()
wait()

start()
Ejecutable En curso
yield()

David Contreras Bárcena 303

David Contreras Bárcena - ETSI


Lenguaje de Programación JAVA – 2º IINF y 2º ITIG
Lenguaje JAVA

11. Threads - Ciclo de vida


Definición: El thread se acaba de crear; todavía no está bajo el
planificador (scheduler).
Ejecutable: El thread está listo para ser ejecutado; se halla en la cola
del planificador del sistema operativo.
En ejecución: El thread está en ejecución hasta que sea sustituido por
otro proceso (p.e., por un algoritmmo de planificación Round Robin) o
hasta que finaliza.
Bloqueado: El thread espera un evento que le permita volver a la cola
del planificador.
Muerto: El thread deja de existir.

David Contreras Bárcena 304

11. Threads - Planificador


El planificador es el encargado de enviar al procesador los
threads según una política de prioridades.
Todos los procesos que llegan al planificador, forman parte
de una cola. El orden dentro de ésta viene dado por su
prioridad y por su instante de llegada.
En caso de tener dos procesos de igual prioridad en la cola,
ejecutará aquel que llegase primero, y posteriormente para
que el proceso no acapare todo el consumo de CPU, se
establecen políticas de rotamiento de procesos: round-robin.

David Contreras Bárcena 305

David Contreras Bárcena - ETSI


Lenguaje de Programación JAVA – 2º IINF y 2º ITIG
Lenguaje JAVA

11. Threads - Planificador


Cuando el planificador suspensde la ejecución de un thread
y pasa el control a otro:
Cuando un thread de mayor prioridad llega al planificador
Cuando el planificador decide ejecutar otro thread de la misma
prioridad (round-robin).
Cuando se produce una situación crítica (por ejemplo: deadlock) y
decide ejecutar un thread de prioridad inferior

David Contreras Bárcena 306

11. Threads - Estructura


Todo thread debe heredar de la clase Thread.
La lógica a ejecutar por el hilo se implementará dentro del método
public void run().
Al finalizar el método run el thread muere.
Este método se invocará automáticamente al realizar el start() del hilo.
public class Hilo extends Thread
{
public Hilo(String nombre)
{
super(nombre);
public class App
}
{
public static void main(String args[])
public void run()
{
{
Hilo h1 = new Hilo(“hilo1”);
//Lógica del hilo
Hilo h2 = new Hilo(“hilo2”);
}
h1.start();
}
h2.start();
}
}

David Contreras Bárcena 307

David Contreras Bárcena - ETSI


Lenguaje de Programación JAVA – 2º IINF y 2º ITIG
Lenguaje JAVA

11. Threads - Cambios de estado


Definición:
Hilo miHilo = new Hilo( );
Inicio:
miHilo.start( ); Æ implícitamente se invoca el método run().
Muerte:
fin de la secuencia de ejecución del método run( )

Bloqueo de un thread : Desbloqueo de un thread :


Thread.sleep(10000); período de tiempo terminado
miHilo.wait( ); miHilo.notify( ) o miHilo.notifyAll( )
espera de recurso(s) recurso(s) liberado(s)

David Contreras Bárcena 308

11. Threads - Cambios de estado


Hilo miHilo = new Hilo( );

miHilo.start(); miHilo.wait(); miHilo.notify();

Estado
ejecución
Estado
bloqueado 1000 ms

Thread.sleep(1000);

Entra en el método Sale del método


run() del hilo run() del hilo

David Contreras Bárcena 309

David Contreras Bárcena - ETSI


Lenguaje de Programación JAVA – 2º IINF y 2º ITIG
Lenguaje JAVA

11. Threads – Finalizar un hilo


Se pueden tener dos tipos de ejecuciones dentro de un hilo:
Secuencial: Se realiza un proceso lineal paralelo al programa
principal. Al ejecutar la última línea de código finaliza el hilo. P.e:
Proceso de impresión en Word.
Iterativo: Se repite el proceso durante toda la ejecución del
programa principal. P.e: Un reloj que se actualiza cada segundo.
Para controlar la finalización del hilo en el segundo caso, se
trabajará con una variable booleana. No se deberá utilizar
public class Hilo extends Thread
{ el método stop() de la clase
private boolean fin = false;
public Hilo(String nombre) Thread (forma insegura).
{ public void run()
super(nombre); {
} while(!fin)
{
public void finalizar() //Lógica del hilo
{ }
fin = true; }
} David Contreras
} Bárcena 310

11. Threads - Prioridades


Las prioridades se establecen de 1 a 10 a través del método
setPriority(int).
También existen constates definidas en la clase Thread que definen la
prioridad máxima, mínima y normal:
MIN_PRIORITY, NORMAL_PRIORITY y MAX_PRIORITY

La forma de suspender externamente (por el programador) un proceso


de su ejecución es a través de la invocación del método yield().

David Contreras Bárcena 311

David Contreras Bárcena - ETSI


Lenguaje de Programación JAVA – 2º IINF y 2º ITIG
Lenguaje JAVA

11. Threads – Acceso concurrente a métodos


Es una de las dificultades de la utilización de threads.
Cuando más de un thread esta intentando modificar los
mismos datos a la vez, el resultado puede ser inconsistente.
class Ipc
{
int sueldo;
..
void incrementaIPC()
{
sueldo*=1.03;
}
}

David Contreras Bárcena 312

11. Threads – Acceso concurrente a métodos


La solución es impedir que dos threads ejecuten
simultáneamente el mismo método.
Esto se consigue gracias al modificador synchronized.

class Ipc
{
int sueldo;
..
synchronized void incrementaIPC()
{
sueldo*=1.03;
}
}

David Contreras Bárcena 313

David Contreras Bárcena - ETSI


Lenguaje de Programación JAVA – 2º IINF y 2º ITIG
Lenguaje JAVA

11. Threads - Ejemplo


public class Corredor extends Thread
{
public static void main(String e[])
{
Corredor c1= new Corredor(“Corredor A");
Corredor c2= new Corredor("Corredor B");
c1.setPriority( Thread.MIN_PRIORITY );
c2.setPriority( Thread.MAX_PRIORITY);
c1.start();
c2.start();
}
public Corredor (String str)
{
super(str);
}
public void run()
{
for (int i = 0; i < 10; i++)
{
System.out.println(i + " " + this.getName());
try
{
Thread.sleep((long)(Math.random() * 1000));
}
catch (InterruptedException e) {}
}
System.out.println("Terminó! " + this.getName());
}
}

David Contreras Bárcena 314

11. Threads – Interface Runnable


Hasta ahora la forma de trabajar con hilos era heredando de
la clase Thread.
Cuando una clase ya hereda de otra (p.e. JFrame) y se
desea trabajar con hilos de ejecución, la solución es
implementar el interface Runnable.
Runnable no define el comportamiento de un hilo, sino la
capacidad de que una clase implemente el método run.
Paralelamente a esto, se deberá crear una ocurrencia de la
clase Thread, índicando a través del constructor
Thread(Runnable), que el método run de este hilo lo
implementará nuestra clase del tipo Runnable.

David Contreras Bárcena 315

David Contreras Bárcena - ETSI


Lenguaje de Programación JAVA – 2º IINF y 2º ITIG
Lenguaje JAVA

11. Threads – Ejemplo de Runnable


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TiraDados extends JFrame implements Runnable
{
private volatile JTextField txtAleatorio = new JTextField (1);
private JButton btnIniciar = new JButton ("Lanzar");
private JButton btnDetener = new JButton ("Parar");
private Thread hiloAleatorio;
private boolean fin = false;
public static void main(String s[])
{
new TiraDados();
}
public TiraDados ()
{
this.getContentPane().setLayout(new FlowLayout());
this.getContentPane().add(txtAleatorio);
this.getContentPane().add(btnIniciar);
this.getContentPane().add(btnDetener);
btnDetener.setEnabled(false);
……

Modificador volatile: es aconsejable declarar de esta manera los


objetos manipulados por más de un hilo

David Contreras Bárcena 316

11. Threads – Ejemplo de Runnable


btnIniciar.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
fin = false;
btnDetener.setEnabled(true);
btnIniciar.setEnabled(false);
hiloAleatorio = new Thread (TiraDados.this);
hiloAleatorio.start();
}
});
btnDetener.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
btnDetener.setEnabled(false);
btnIniciar.setEnabled(true);
fin = true;
}
});
this.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
fin = true;
TiraDados.this.dispose();
System.exit(0);
}
});

David Contreras Bárcena 317

David Contreras Bárcena - ETSI


Lenguaje de Programación JAVA – 2º IINF y 2º ITIG
Lenguaje JAVA

11. Threads – Ejemplo de Runnable


this.pack();
this.setVisible(true);
}
public void run()
{
while(!fin)
{
try
{
Thread.sleep(1000);
int a = (int) (Math.random()*6) + 1;
txtAleatorio.setText(String.valueOf(a));
}
catch(InterruptedException e)
{
}
}
}
}

David Contreras Bárcena 318

11. Threads – Wait y Notify


Establecen un mecanismo seguro para detener y recuperar
la ejecución del thread.
No se deberá hacer uso de los métodos suspend() o
resume().
Los dos métodos deben ejecutarse en fragmentos de código
synchronized. Esto se puede hacer definiendo el método
con este modificador o definiendo un bloque.

public synchronized void metodo() public void metodo()


{ {
… synchronized (this)
} {

}
}

David Contreras Bárcena 319

David Contreras Bárcena - ETSI


Lenguaje de Programación JAVA – 2º IINF y 2º ITIG
Lenguaje JAVA

11. Threads – Wait y Notify


public void detener ()
{
hiloDetenido = true;
}
public synchronized void reanudar()
{
hiloDetenido = false;
this.notify();
}
public void run()
{
while(!fin)
{
txtCrono.setText(String.valueOf(++contador*1000));
try
{
Thread.sleep(1000);
synchronized(this)
{
while(hiloDetenido)
this.wait();
}
}
catch(InterruptedException e)
{}
}
}

David Contreras Bárcena 320

11. Threads – Join


Permite conocer cuando finaliza la ejecución de un hilo.
Una vez que se invoque el método join() de un thread, el
programa quedará a la espera de la finalización del mismo.
Existe también el método sobrecargado join(long) que
permitirá no estar esperando a la finalización del hilo más del
tiempo especificado. En el momento que dé cualquiera de
los dos eventos (cumplido el tiempo o finalizado el thread),
se deshará la espera.

David Contreras Bárcena 321

David Contreras Bárcena - ETSI


Lenguaje de Programación JAVA – 2º IINF y 2º ITIG
Lenguaje JAVA

11. Threads – Join


public class AppJoin extends Thread
{
public static void main(String args[])
{
AppJoin thread = new AppJoin();
thread.start();
try
{
System.out.println("Esperando a que acabe el hilo");
//thread.join(); //espera a que se termine el hilo
thread.join(1000); //espera como mucho ese tiempo
System.out.println("Hilo finalizado");
}
catch (InterruptedException e) {}
}
public void run()
{
try
{
Thread.sleep(5000);
}
catch (InterruptedException e) { }
}
}

David Contreras Bárcena 322

11. Threads – Otras formas de trabajar


Redefiniendo el método deprecated stop().
Controlar el hilo que entra en el run.
De esta manera se podría ejecutar el método sleep(long)
sobre la instancia.
private volatile Thread hilo;

public void stop()


{
hilo = null;
}
public void run()
{
Thread hiloActual = Thread.currentThread();
while (hilo == hiloActual)
{
try
{
hiloActual.sleep(1000);
}
catch (InterruptedException e){ }
}
}

David Contreras Bárcena 323

David Contreras Bárcena - ETSI


Lenguaje de Programación JAVA – 2º IINF y 2º ITIG
Lenguaje JAVA

11. Threads – Daemon


Los daemon son los threads que proporcionan uno o varios
servicios a otros threads. El método run( ) de un daemon
está generalmente constituido por un bucle infinito en espera
de llamadas de servicios.
Para establecer el atributo daemon a un thread :
miThread.setDaemon( )
Para saber si un thread es un daemon : miThread.isDaemon( )

David Contreras Bárcena 324

11. Threads – Grupos de thread


Todo thread Java forma parte de un grupo de thread que es
una instancia de la clase ThreadGroup (java.lang). La
máquina virtual Java establece un grupo por defecto a todo
thread nuevo.
Operaciones que se pueden realizar a nivel de grupo::
obtener datos (elementos del grupo,...)
modificar los atributos del grupo (prioridad máxima, ”daemon")
modificar el estado del conjunto de thread del grupo

ThreadGroup miGrupo = new ThreadGroup(”grupo1");


Thread thread1 = new Thread (miGrupo,"thread1");
Thread thread2 = new Thread (miGrupo,"thread2");
thread1.start( );
thread2.start( );

David Contreras Bárcena 325

David Contreras Bárcena - ETSI


Lenguaje de Programación JAVA – 2º IINF y 2º ITIG
Lenguaje JAVA

11. Threads - Métodos de Thread


start();
sleep(long);
setName(String);
getName();
setPriority(int);
getPriority();
wait();
notify();

stop(); //No se debe utilizar


suspend(); //No se debe utilizar
resume(); //No se debe utilizar

David Contreras Bárcena 326

11. Threads – Métodos de Grupos


getmaxPriority(): devuelve la prioridad máxima del grupo
setMaxPriority(int): modifica la prioridad máxima del grupo
setDaemon(boolean): establece el status ”daemon" al grupo, el grupo es
destruido cuando todos los elementos están muertos.

David Contreras Bárcena 327

David Contreras Bárcena - ETSI

Вам также может понравиться