Está en la página 1de 30

1

Notas:
J .M. Drake
L. Barros
PROGRAMACION CONCURRENTE Y
DISTRIBUIDA
III.1 Concurrencia con Java: Thread Java
2
Notas:
2
Procodis09: III.1- ThreadJ ava J osM.Drake
Concurrencia en Java.
J ava posibilita la programacin concurrente a travs de
threads.
Los threadsson procesos ligeros, con lnea de flujo de control
propia pero que comparte el espacio de direcciones del
programa.
Los threadshacen posible la ejecucin concurrente de cdigo.
Los cambios de contexto son menos costosos en tiempo de ejecucin.
J ava es un lenguaje que permite formular programas concurrentes. Esto es, existen en J ava
sentencias que permiten construir un programa con mltiples lneas de flujo de control ( threads) que
se ejecutan concurrentemente si la plataforma es multiprocesadorao que ejecutan de forma
entralazadasus sentencias dando apariencia de concurrencia si la plataforma es monoprocesadora.
La unidad bsica de concurrencia en J ava es el Thread, que representa un proceso ligero que
comparte el mismo espacio de variables con los restantes threadsdel mismo programa. Dado que los
Threadsde un programa J ava son todos ellos internos al programa, no senecesita la proteccin de
seguridad de disponer de un nico espacio de variables propio de cada threads, y al tener un espacio
de memoria nico se aligera y facilita los cambios de contexto entre threads.
Como se ha visto en los captulos previos del curso la concurrencia proporciona muchas ventajas
de programacin, tanto en la gestin de entradas y salidas, de dispositivos externos o de las
interacciones con el usuario, como para hacer que la estructura del programa sea mas prxima al
dominio del problema al facilitar la programacin orientada a objetos y con objetos activos.
En contrapartida la programacin concurrente requiere abordar nuevos situaciones sobre
sincronizacin entre threadsy acceso de forma segura a los objetos compartidos, por lo que el
lenguaje J ava debe proporcionar sentencias y recursos que permitan abordarlas.
3
Notas:
3
Procodis09: III.1- ThreadJ ava J osM.Drake
Class Thread
Un threadse crea en J ava instanciandoun objeto de la clase
Thread.
El cdigo que ejecuta un threadestdefinido por el mtodo
run() que tiene todo objeto que sea instancia de la clases Thread.
La ejecucin del thread se inicia cuando sobre el objeto Thread
se ejecuta el mtodo start().
De forma natural, un thread termina cuando en run() se alcanza
una sentencia return o el final del mtodo. (Existen otras formas
de terminacin forzada)
Para declarar un threaden un programa J ava se debe instanciar un objeto que sea una extensin
(extends) la clase java.lang.Thread. Por cada objeto de con estas caractersticas que se declare en
un programa java, se crea un nuevo threadcon una lnea de flujo de control propia que se ejecutar
concurrentemente con el programa principal y con los restantes threads.
El cdigo que ejecuta un threades el expresado atravsde su mtodo run(), que es heredado de la
clase Thread. A fin de definir la actividad que se quiere que ejecute el nuevo threades necesario
sobreescribir el mtodo run() original con un cdigo que establezca la actividad deseada.
La ejecucin del threadcreado con la instanciacinde un objeto derivado de Threadscomienza
cuando se invoca en el programa principal (o en otro threadactivo) el mtodo start del objeto.
Existen muchas formas de concluir un threads. La natural es cuando en el mtodo run() que define
su actividad, se alcanza alguna sentencia end. Ms adelante se analizarn otros mtodos heredados
de Threadque permiten abortar o elevar excepciones en el thread, y que pueden conducir a su
finalizacin.
4
Notas:
4
Procodis09: III.1- ThreadJ ava J osM.Drake
Constructores de la clase Thread.
Thread()
Thread(RunnablethreadOb)
Thread(RunnablethreadOb, StringthreadName)
Thread(StringthreadName)
Thread(ThreadGroupgroupOb, RunnablethreadOb)
Thread(ThreadGroupgroupOb, RunnablethreadOb,
StringthreadName);
Thread(ThreadGroupgroupOb, StringthreadName)
Existen varios constructores de la clase Thread(y transferido por herencia a todas su extensiones).
Desde el punto de vista estructural existen dos variantes bsicas:
- Las que requieren que el cdigo del mtodo run() se especifique explcitamente en la declaracin
de la clase.
Por ejemplo: Thread(StringthreadName)
- Las que requieren un parmetro de inicializancinque implemente la interfaz Runnable.
Por ejemplo: Thread(RunnablethreadOb)
Los restantes constructores resultan de si se asigna un nombre la threads, y que solo afecta para
inicializar ese atributo en la instancia del objeto, y pueda utilizarse para que en fases de verificacin
cada threadpueda autoidentificarse, o de si se le crea dentro de un ThreadGroup, lo cual limita su
accesibilidad y su capacidad de interaccin con threadsque han sido creados en otros ThreadGroup.
5
Notas:
5
Procodis09: III.1- ThreadJ ava J osM.Drake
Creacin de un thread por herencia.
public class PingPongextends Thread{
private Stringword; // Lo que va a escribir.
private int delay; // Tiempo entre escrituras
public PingPong(StringqueDecir,int cadaCuantosMs){
word=queDecir; delay=cadaCuantosMs; };
public void run(){ //Se sobrescribe run() de Thread
while(true){
System.out.print(word+ );
try{
sleep(delay);
} catch(InterruptedExceptione){ return; }
}
}
}
public static void main(String[] args){
// Declaracin de 2 threads
PingPongt1 =newPingPong(PING,33);
PingPongt2=newPingPong(PONG,10);
// Activacin
t1.start();
t2.start();
// Espera 2 segundos
try{ sleep(5000);
}catch(InterruptedExceptione){};
// Finaliza la ejecucin de los threads
t1.stop();
t2.stop();
}
}
La clase java PingPonges una extensin de la clase Threads, por lo que cada una de sus instancias
(por ejemplo t1 y t2 representan un nuevo threadjava.
El metodorun() es sobreescritoen la clase PingPong, y establece el cdigo que se ejecutaren
cada instancia de la clase. En el ejemplo consiste en un bucle indefinido de escribir el valor del
atributo word, y de suspenderse durante los milisegundos expresador en el atributo delay.
La sentencia try.. catchtiene que ser utilizada porque el mtodo sleeppuede elevar una excepcin
del tipo InterruptException.
Con las sentencias que declaran e instancianlos dos objetos t1 y t2 de la clase PingPongse han
creado dos threads. La creacin supone que a los threadse les ha dotado de los recursos que
requieren, pero aun estn inactivos (esto es no se estejecutando las sentencias de su mtodo run()).
Con las sentencias que invocan los mtodos t1.start() y t2.start() de los objetos de la clase
PingPong, se inicia en la ejecucin del cdigo de los respectivos procedimiento run().
En este caso (para hacer el ejemplo sencillo) los threadsno finalizan nunca (observeseel bucle
while(true) de los mtodos run()). Se acabarn desde el entorno abortando el programa principal y
todo lo que depende de l.
6
Notas:
6
Procodis09: III.1- ThreadJ ava J osM.Drake
Interface Runnable
Definicin de la interfaceRunnable:
public interface Runnable{
public abstract void run();
}
Creacin de un threada partir de la interfaceRunnable:
1) public class MiClaseimplements Runnable{
public void run(){ ......}
}
2) .....
MiClase ot =new MiClase();
Threadt1 =new Thread(ot);
t1.start();
.....
Clase raz dominio
Clase activa
<<interface>>
Runnable
Thread
+run()
+run()
Clase activa
+run()
Thread
La segunda posibilidad de crear un threades a travs de la utilizacin de un objeto que
implemente la interfaceRunnable, y con el que se incorpora el mtodo run() que establece las
actividades que va a realizar.
La clase MiClaseimplementa la interfaz Runnable, y por ello se le requiere que establezca el
cdigo del mtodo abstracto run() al que obliga ser la implementacin de la interfaz Runnable.
En el programa que declara el nuevo thread, se debe declarar primero el objeto t1 de la clase
MiClase, y posteriormente cuando se crea el threads(se instancia el objeto t1 de la clase Thread) se
le pasa como parmetro de su constructor.
Este es el procedimiento mas habitual de crear threadsen java, ya que permite herencia mltiple,
al poder ser la clase Runnableextensin de cualquier otra clase que ya estdefinida.
7
Notas:
7
Procodis09: III.1- ThreadJ ava J osM.Drake
Creacin de Thread a travs de la interfaz
Runnable.
public class PingPongimplements Runnable{
private Stringword; // Lo que va a escribir.
private int delay; // Tiempo entre escrituras
public PingPong(StringqueDecir, int cadaCuantosMs){
word=queDecir; delay=cadaCuantosMs; };
public void run(){
while(true){
System.out.print(word+ );
try{ sleep(delay);
}catch(InterruptedExceptione){return;}
}
}
}
public class PruebaRunnable{
public static void main(String[] args){
// Los objetos r1 y r2 definen la funcionalidad.
// (definen los mtodos run())
PingPongr1 =new PingPong(PING,33);
PingPongr2=new PingPong(PONG,10);
// Se crean los threads
Threadt1 =newThread(r1);
Threadt2=newThread(r2);
// Se activan los threads
t1.start();
t2.start();
}
}
La clase PingPongimplementa la interfaz Runnable, y en consecuencia define el mtodo run() que
constituirel cuerpo de futuros threads.
Aun que no ocurre en el ejemplo, la clase PingPongpodra ser una extensin de otra clase, de la
que heredara su funcionalidad y sus recursos.
Cuando instancianlos threadst1 y t2 (en este caso directamente de la clase Thread, aunque podra
ser de cualquier otra derivada de ella), se le pasa como valor actual del parmetro Runnable
threadObdel constructor, los objetos Runnablesr1 y r2 de la clase PingPongque fueron previamente
instanciados.
La declaracin de los objetos runnablespodra ser directa dentro de la declaracin de los threads,
solo que en ese caso seran annimos:
PingPongt1 =newThread(newPingPong(ping,33));
PingPongt2 =newThread(newPingPong(PONG,100));
O incluso con los threadtambin annimos:
newThread(newPingPong(ping,33));
newThread(newPingPong(PONG,100));
8
Notas:
8
Procodis09: III.1- ThreadJ ava J osM.Drake
Delegacin en una operacin costosa en un thread
public class threadAgente{
....
public void operacionCostosa(){
....
};
static public void main(String[] args}{
....
// Lanza la ejecucin costosa en un thread annimo concurrente
new Thread(
new Runnable(){
public void run(){ operacionCostosa();}
}
).start();
//main ejecuta concurrentemente otra tarea de inters
....
};
}
9
Notas:
9
Procodis09: III.1- ThreadJ ava J osM.Drake
Clase activa con thread auto lanzado
public class SelfRunimplements Runnable{
private ThreadinternalThread;
private boolean noStopRequired;
public SelfRun(){
System.out.println("Comienza ejecucin");
noStopRequired=true;
internalThread=new Thread(this);
internalThread.start(); }
public void run(){
while(noStopRequired){
System.out.println("En ejecucin");
try{ Thread.sleep(500);
}catch (InterruptedExceptione){
Thread.currentThread().interrupt();}
}
}
public void stopRequest(){
noStopRequired=false;
internalThread.interrupt();}
public static void main(String[] args) {
SelfRunobjActivo=new SelfRun();
// Espera durante 2 segundos
try{Thread.sleep(2000);
}catch(InterruptedExceptione){};
// Termina el objeto activo
System.out.println("maininvoca stopRequest()");
objActivo.stopRequest();
}
}
Respuesta del programa:
Comienza ejecucin
En ejecucin
En ejecucin
En ejecucin
En ejecucin
En ejecucin
main invoca stopRequest()
10
Notas:
10
Procodis09: III.1- ThreadJ ava J osM.Drake
Mtodos de la clase Thread: Inicio y finalizacin.
voidrun()
Contiene el cdigo que ejecuta el thread.
voidstart()
Inicia la ejecucin del thread.
voidstop()
Termina la ejecucin del thread(*)
staticThreadcurrentThread()
Retorna el objeto Threadque ha ejecutado este mtodo.
final voidsleep(longmilliseconds) throws InterruptedException
Suspende la ejecucin del threadpor el nmero de milisegundos
especificados.
El mtodo stop() es muy inseguro. Si se destruye un threadcon recursos tomados estos
permanecen tomados y no accesibles a otros componentes de la aplicacin. Es un mtodo ya
obsoleto que sereliminado en las prximas versiones. Un threaddebe terminarse utilizando el
mtodo interrupt().
El mtodo sleeppuede lanzar la excepcin InterruptedException(lo que ocurre si mientras que el
threadestsuspendido, otro threadsejecuta el mtodo Interrupt de l). Por esta razn, el mtodo
sleepdebe ejecutarse siempre dentro de una sentencia try.. catch:
try{
....
sleep(500);
....
}
catch(InterruptedExceptione {...};
11
Notas:
11
Procodis09: III.1- ThreadJ ava J osM.Drake
Ejemplo de uso del mtodo currentThread().
public class Clienteextends Thread{
public void run(){
Recurso.uso();
try {
Thread.sleep(2000);
} catch(InterruptedExceptione){};
};
}
public class Recurso{
static synchronized void uso(){
Threadt =Thread.currentThread();
System.out.println(Soy+t.getName());
}
}
public static void main(String[]
args){
Clientejuan=new Cliente();
juan.setName(J uan Lpez");
Clienteines=new Cliente();
ines.setName(Ins Garca");
juan.start();
ines.start();
}
}
En el ejemplo se instancianvarios threads(juane ines) del tipo Cliente que es una extensin de la
clase Thread.
En la definicin de su actividad (mtodo run()), invocan el mtodo uso de un objeto construido
con la clase esttica Recurso.
Dentro del objeto Recurso cada threadse autoidentificaa travs del mtodo currentThread,( y en
este caso imprime su identificador por defecto: nombre,prioridad, Grupos, etc.). Con ello, se puede
escribir en un recurso compartido por muchos threadssentencias que se particularicen en funcin de
que threadlo estvisitando.
El nombre de los threadse establece a travs del mtodo setName, se podra haber hecho de forma
equivalente a travs del contructor:
Cliente juan=newCliente(J uan Lpez);
Cliente ines=newCliente(InesGarca);
12
Notas: 12
Procodis09: III.1- ThreadJ ava J osM.Drake
Estados de un thread
UnStarted Runnable
Suspended
Interrupted Dead
Waiting
Sleeping
stop()
interrupt()
interrupt()
interrupt()
interrupted()
notify() wait()
suspend()
resume()
sleep()
timeout
start()
Alive
Estado UnStarted: El threadha sido instanciadopero no se arrancado su ejecucin.
Estado Alive: El cdigo del mtodo run() se estejecutando.
SubestadoRunnable: La ejecucin del threadesta siendo planificada por el procesador.
SubestadoInterrupted: La ejecucin del threadestsiendo planificada por el procesador,
pero ero se ha invocado el mtodo Interrupt sobre el thread.
SubestadoSuspended: El threadestsupendidoindefinidamente (porque sobre l se ha
invocado el mtodo suspend(). El threadno estsiendo planificado.
SubestadoSleeping: El threadestsupendidotemporalmente (durante el nmero de ms
establecido por el argumento del mtodo sleep() que lo ha dormido).
SubestadoWaiting: El threadestsupendidoindefinidamente (sobre la variable de condicin
del objeto threadpor haber invocado el mismo el mtodo wait()).
Estado Dead: El threadha finalizado. Un threadfinaliza por uno de los tres siguientes modos:
- El mtodo run() ejecuta la sentencia returno alcanza su final.
- Se invoca desde un threadactivo el mtodo stop().
- No se recupera la excepcin InterruptedExceptionestando en Waitingo Sleeping.
13
Notas:
13
Procodis09: III.1- ThreadJ ava J osM.Drake
Mtodos de la clase Thread: Control de finalizacin.
final booleanisAlive()
Retorna truesi el threadse encuentra en el estado Alive(en alguno de sus
subestados), esto es, ya ha comenzado y aun no ha terminado.
final voidjoin() throwsInterruptedException
Suspende el threadque invoca hasta que el threadinvocado haya
terminado.
final voidjoin(longmilliseconds) throwsInterruptedException
Suspende el threadque invoca hasta que el threadinvocado haya
terminado o hasta que hayan transcurrido los milisegundos.
14
Notas:
14
Procodis09: III.1- ThreadJ ava J osM.Drake
Ejemplo de uso del mtodo isAlive().
public class Obreraextends Thread{
private Stringresultado ="No calculado";
public void run(){
resultado =calcula();
}
private Stringcalcula(){
// Realiza un clculo largo.
try {Thread.sleep(10000);
} catch(InterruptedExceptione){};
return "Ya calculado";
}
public StringgetResultado(){
return resultado;
}
}
class Ejemplo_isAlive{
public static void main(String[] args){
Obrera agente=new Obrera();
agente.start();
// Hace algo durante el clculo.
......
//Espera que agente haya terminado
while (agente.isAlive()) Thread.yield();
// Utiliza el resultado.
System.out.println(agente.getResultado());
}
}
El programa principal main instancia el threadagente de la clase Obrera (es un thread
porque es una extensin de Thread), y delega en l que para que invoque y ejecute Calcula().
Concurrentemente el programa mainejecuta alguna otra actividad. Cuando finaliza se introduce
en un lazo de espera activa en el que haciendo uso del mtodo isAliveespera a que la Obrera agente
haya concluido.
Luego lee de ella el resultado. Observeseque aunque ha concluido se pueden acceder a su
variable resultado a travs del mtodo getResultado().
ESTE ES UN PROGRAMA MAL DISEADO PORQUE REQUIERE UNA ESPERA ACTIVA.
15
Notas:
15
Procodis09: III.1- ThreadJ ava J osM.Drake
Ejemplo de uso del mtodo join()
public class Obreraextends Thread{
private Stringresultado ="No calculado";
public void run(){
resultado =Calcula();
}
StringCalcula(){
// Realiza un clculo largo.
try {Thread.sleep(10000);
}catch(InterruptedExceptione){};
return "Ya calculado";
}
public StringgetResultado(){
return resultado;
}
}
class Ejemplo_join{
public static void main(String[] args){
Obreraagente=new Obrera();
agente.start();
// Hace algo durante el clculo.
try { //Espera a que agente termine
agente.join();
}catch (InterruptedExceptione){};
// Utiliza el resultado.
System.out.println(agente.getResultado());
}
}
Este programa tiene la misma funcionalidad que el programa de la pgina anterior (12).
Sin embargo este programa es mucho mas eficiente, esto es requerirmenos tiempo de CPU para
ser ejecutado, ya que la espera ahora es suspendida (Waiting). El programa principal maininvoca el
mtodo joinsobre el threadObrera agente. Mainpasa a estado Waitingy espera suspendido all hasta
que tras la finalizacin del threadagente, lo retorna al estado Runnable.
La invocacin del mtodo joinhay que invocarlo dentro de una sentencia try.. catch, ya que si
sobre mainse invoca el mtodo interrupt, se elevara la excepcin InterruptedException.
16
Notas:
16
Procodis09: III.1- ThreadJ ava J osM.Drake
Mtodos de la clase Thread: Interrupcin.
voidinterrupt()
El threadpasa a estado Interrupted. Si esten los estados Waiting,
J oiningo Sleeping termina y lanza la excepcin InterruptedException.
Si esten estado Runnable, continua ejecutndose aunque cambia su
estado a Interrupted.
staticbooleaninterrupted()
Procedimiento esttico. Retorna truesi el threadque lo invoca se
encuentra en estado Interrupted. Si estuviese en el estado Interrupted
se pasa al estado Runnable.
booleanisInterrupted()
Retorna truesi el objeto threaden que se invoca se encontrase en el
estado Interrupted. La ejecucin de este mtodo no cambia el estado
del thread.
17
Notas:
17
Procodis09: III.1- ThreadJ ava J osM.Drake
Uso del mtodo isInterrupted().
public class InterruptCheck {
public static void main(String[] args) {
Threadt=Thread.currentThread();
System.out.println("A:t.isInterrupted()="+t.isInterrupted());
t.interrupt();
System.out.println("B:t.isInterrupted()="+t.isInterrupted());
System.out.println("C:t.isInterrupted()="+t.isInterrupted());
try{
Thread.sleep(2000);
System.out.println("No ha sido interrumpida");
}catch(InterruptedExceptione){
System.out.println("Si ha sido interrumpida");
}
System.out.println("D:t.isInterrupted()="+t.isInterrupted());
}
Respuesta del programa:
A:t.isInterrupted()=false
B:t.isInterrupted()=true
C:t.isInterrupted()=true
No ha sido interrumpida
D:t.isInterrupted()=false
No cambia
18
Notas:
18
Procodis09: III.1- ThreadJ ava J osM.Drake
Uso del metodo esttico Thread.interrupted()
public class InterruptReset {
public static void main(String[] args) {
Threadt=Thread.currentThread();
System.out.println("A: Thread.interrupted()="+Thread.interrupted());
t.interrupt();
System.out.println("B: Thread.interrupted()="+Thread.interrupted());
System.out.println("C: Thread.interrupted()="+Thread.interrupted());
try{
Thread.sleep(2000);
System.out.println("No ha sido interrumpida");
}catch(InterruptedExceptione){
System.out.println("Si ha sido interrumpida");
}
System.out.println("D: t.isInterrupted()="+t.isInterrupted());
}
}
Respuesta del programa:
A: Thread.interrupted()=false
B: Thread.interrupted()=true
C: Thread.interrupted()=false
No ha sido interrumpida
D: t.isInterrupted()=false
cambia
19
Notas:
19
Procodis09: III.1- ThreadJ ava J osM.Drake
Ejemplo de finalizacin por InterruptedException.
public class MiThreadextends Thread{
public void run(){
while (true) {
System.out.println("Ejecuto");
try{
Thread.sleep(100);
}catch (InterruptedExceptione){
System.out.println("Termino ensleep");
};
};
return;
}
}
public class Ejemplo_Fin_por_Interrupt {
public static void main(String[] args){
ThreadelThread=new MiThread();
elThread.start();
try{
Thread.sleep(1000);
}catch (InterruptedExceptione){};
elThread.interrupt();
}
}
El threadelThread ejecuta un bucle peridico que escribe Ejecuto y luego se suspende durante
100 ms.
El programa principal main, espera durante un tiempo (1000 ms) y luego invoca el mtodo
interrupt() del threadelThread.
Cuando se invoca el mtodo interrupt() elTthreadpuede estar en uno de dos estados:
- Si esten el estado Runnable, pasa al estado Interruptedhasta que se invoque el
mtodo sleep() y pase al estado
Sleeping, instante en el que se eleva la excepcin InterruptedExceptionen
elThread, y tras escribir el comentario finaliza
elThread.
- Si esten el estado Sleeping, se eleva de forma inmediata la excepcin
InterruptedExceptionen elThread, y tras escribir
el comentario finaliza elThread.
20
Notas:
20
Procodis09: III.1- ThreadJ ava J osM.Drake
Ejemplo de uso de interrupt() e interrupted()
public class MiThreadextends Thread{
public void run(){
while (!Thread.interrupted()) {
System.out.println("Ejecuto");
};
System.out.println(Termino");
return;
}
}
public class Ejemplo_Fin_por_Interrupt {
public static void main(String[] args){
ThreadelThread=new MiThread();
elThread.start();
try{
Thread.sleep(1000);
}catch (InterruptedExceptione){};
elThread.interrupt();
}
}
En este caso, elThreadpermanece permanentemente es el estado Runnable, ejecutando la escritura
del texto Ejecuto en un bucle indefinido que perdura mientas que el resultado de invocar
interrupted() sea false.
Cuando tras 1000 msmaininvoque el mtodo interrupted() sobre elThread, este pasa a estado
Interrupted, y en la siguiente ejecucin de la sentencia whilesale del bucle, y tras escribir el texto de
salida, ejecuta returny concluye.
21
Notas:
21
Procodis09: III.1- ThreadJ ava J osM.Drake
Interrupcin durante sleep
public class SleepInterrupt implements Runnable{
public void run(){
try{
System.out.println("in run(): me duermo 20 s");
Thread.sleep(20000);
System.out.println("in run(): me despierto");
}catch (InterruptedExceptione){
System.out.println(
"in run(): interrumpida en sleep");
return;
}
System.out.println("in run(): fin normal");
}
....
...
public static void main(String[] args) {
SleepInterrupt si=new SleepInterrupt();
Threadt=new Thread(si);
t.start();
try{
Thread.sleep(1000);
}catch (InterruptedExceptione){};
System.out.println("in main(): Intterupoa t");
t.interrupt();
System.out.println("in main(): termina");
}
}
Respuesta del programa:
in run(): me duermo 20 s
in main(): Intterupo a t
in run(): interrumpida en sleep
in main(): termina
22
Notas:
22
Procodis09: III.1- ThreadJ ava J osM.Drake
Interrupcin pendiente y sleep()
public class PendingInterrupt {
public static void main(String[] args) {
if (args.length>0){ Thread.currentThread().interrupt();}
long tiempoInicial=System.currentTimeMillis();
try{
Thread.sleep(2000);
System.out.println("No es interrumpida");
}catch (InterruptedExceptione){
System.out.println("Es interrumpida");
}
System.out.println("Tiempo gastado: "+
(System.currentTimeMillis()-tiempoInicial));
}
}
Respuesta a java PendingInterrupt:
No es interrumpida
Tiempo gastado: 2000
Respuesta a java PendingInterrupt yes:
Es interrumpida
Tiempo gastado: 0
23
Notas:
23
Procodis09: III.1- ThreadJ ava J osM.Drake
Mtodos suspend() y resume() de la clase Thread.
El mtodo suspend() permiten parar reversiblemente la
ejecucin de un Thread. Se reanuda cuando sobre l se ejecute
el mtodo resume().
Ejecutar suspendsobre un threadsuspendido o ejecutar
resume() sobre un threadno suspendido no tiene ningn
efecto.
publicfinal voidsuspend()
Suspende la ejecucin del thread. Los objetos sobre los que tena derecho
de acceso quedan cerrados para el acceso de otros threadshasta que tras
que le sea aplicado resume(), los libere.
publicfinal voidresume()
Reanuda el threadsi ya estuviera suspendido.
Los metodossuspend() y resume() sereliminado en futuras versiones de java, al igual que el
mtodo stop() ya que son muy proclives a provocar bloqueos.
24
Notas:
24
Procodis09: III.1- ThreadJ ava J osM.Drake
Ejemplo de aplicacin de mtodos suspend() y resume()
El procedimiento ConfirmaCancelacion() suspende la actividad del
threadque se pasa como el argumento elThread, mientras se confirma
su abandono definitivo.
public void ConfirmaCancelacion(ThreadelThread) {
elThread.suspend();
if (DebeCancelarse(Realmente se cancela?))
elThread.interrupt();
else
elThread.resume();
}
El ejemplo consiste en el procedimiento ConfirmaCancelacionpara confirmar la suspensin
definitiva de un threadque se pasa como el argumento elThread.
Inicialmente se invoca sobre l el mtodo suspend() para suspenderlo hasta que el operador haya
establecido su destino.
Posteriormente se del operador que confirme o cancele la suspencin. En el primer caso, se invoca
el mtodo interrupt() para provocar la cancelacin ordenada del thread, y en el segundo caso se
invoca el mtodo resume() para que contine desde donde se suspendi.
25
Notas:
25
Procodis09: III.1- ThreadJ ava J osM.Drake
Mtodos de la clase Thread: Control de planificacin.
Constantes
MAX_PRIORITY //Mxima prioridad asignable al thread.
MIN_PRIORITY //Mnima prioridad asignable al thread.
NORM_PRIORITY //Prioridad por defecto que se asigna.
Mtodos
final voidsetPriority(int priority)
Establece la prioridad de Thread.
final int getPriority()
Retorna la prioridad que tiene asignada el thread.
staticvoidyield()
Se invoca el planificador para que se ejecute el threaden espera que
corresponda.
La planificacin de los threadestpobremente establecida en java, ya que no es un lenguaje de
tiempo real, y la mayora de las Maquinas virtuales java no son sensibles a la prioridadde los
threads.
De acuerdo con la especificacin original la planificacin debera realizarse con una poltica
expulsora (pre-emptive) y basada en prioridades.
Cada clase especializada de Thread, ofrece tres atributos constantes que pueden ser ledos y que
expresan los lmites de prioridades (MAX_PRIORITY,MIN_PRIORITY) que pueden asignarse a
cada threadde la clase, y el valor de prioridad por defecto (NORM_PRIORITY).
La norma de planificacin establece que el planificador nunca planifica un threadde entre los que
se encuentran en el estado Runnableo Interruptedsi hay otro threaden los citados estados con mayor
prioridad asignada que l.
26
Notas:
26
Procodis09: III.1- ThreadJ ava J osM.Drake
Manejo de prioridades
public class SimplePrioritiesextends Thread{
private int countDown=5;
private volatile double d =0; // No optimization
public SimplePriorities(int priority) {
setPriority(priority);
start();
}
public StringtoString() {
return super.toString() +": " +countDown;
}
public void run() {
while(true) {
// Anexpensive, interruptableoperation:
for(int i =1; i <100000; i++)
d =d +(Math.PI +Math.E) / (double)i;
System.out.println(this);
synchronized(this){
if(--countDown==0) return;
}
}
}
public static void main(String[] args) {
new SimplePriorities(Thread.MAX_PRIORITY);
for(int i =0; i <5; i++)
new SimplePriorities(Thread.MIN_PRIORITY);
}
}
27
Notas:
27
Procodis09: III.1- ThreadJ ava J osM.Drake
Mtodos de la clase Thread: Debuging y control.
StringtoString()
Retorna un stringcon el nombre, prioridad y nombre del grupo del
Thread.
final StringgetName()
Retorna el nombre del Thread
final voidsetName(StringthreadName)
Establece el nombre del Thread.
staticint activeCount()
Retorna el nmero de threadsactivos en el grupo al que pertenece el
threadque invoca.
final ThreadGroupgetThreadGroup()
Retorna el grupo al que pertenece el threadque invoca.
Son mtodos que se utilizan habitualmente en las fase de validacin de los programas.
28
Notas:
28
Procodis09: III.1- ThreadJ ava J osM.Drake
Mtodos de la clase Thread: Daemon.
Existen dos tipos de threaduser y daemon. Su diferencia radica en su
efecto sobre la finalizacin de la aplicacin a la que pertenecen.
Una aplicacin termina solo si han terminado todos los threadsde tipo user.
Cuando todos los threadsde tipos user han terminado los threadde tipo
Daemonson terminados con independencia de cual sea su estado y la
aplicacin es finalizada.
Metodosrelativos al tipo de Thread.
final voidsetDaemon(booleanstate)
Convierte un threaden daemon. Solo es aplicable despus de haber creado
el thready antes de que se haya arrancado (start).
final booleanisDaemon()
Retorna truesi el threades de tipo daemon.
29
Notas:
29
Procodis09: III.1- ThreadJ ava J osM.Drake
Ejemplo de thread Daemond
public class DaemondThreadimplements Runnable{
public void run(){
System.out.println(Comienzarun());
try{
while (true){
try{Thread.sleep(500);
}catch (InterruptedExceptione){};
System.out.println(run() ha despertado);
}
}finally{
System.out.println(Terminarun());
}
}
public static void main(String[] args){
System.out.println(Comienzamain());
Threadt=newThread(newDaemondThread());
t.setDaemon(true);
t.start();
try{Thread.sleep(2000);
}catch (InterruptedExceptione){};
System.out.println(Terminamain());
}
}
Respuesta de la ejecucin de main()
Comienza main()
Comienza run()
run() ha despertado
run() ha despertado
run() ha despertado
run() ha despertado
Termina main()
run() ha despertado
Los threadque han sido cualificado como daemonterminan de una forma diferente. Cuando la VM
detecta que slo permanecen en ejecucin threadDaemontermina su ejecucin.
Los daemonthreadson utilizados para ejecutar tareas auxiliares de otros threadnormales, cuando
estos han terminado aquellos no tienen funcin y finalizan.
En el ejemplo es interesante comprobar que cuando finaliza main, y la VM descubleque slo queda
el threadt , este finaliza de forma abrupta y no sale normalmente por larama finally.
30
Notas:
30
Procodis09: III.1- ThreadJ ava J osM.Drake
Ejemplo de thread User
public class DaemondThreadimplements Runnable{
public void run(){
System.out.println(Comienzarun());
try{
while (true){
try{Thread.sleep(500);
}catch (InteruptedExceptione){};
System.out.println(run() ha despertado);
}
}finally{
System.out.println(Terminarun());
}
}
public static void main(String[] args){
System.out.println(Comienzamain());
Threadt=newThread(newDaemonThread());
t.setDaemon(true);
t.start();
try{Thread.sleep(2000);
}catch (InterruptedExceptione){};
System.out.println(Terminamain());
}
}
Respuesta de la ejecucin de main()
Comienza main()
Comienza run()
run() ha despertado
run() ha despertado
run() ha despertado
run() ha despertado
Termina main()
run() ha despertado
run() ha despertado
....
Los threadque han sido cualificado como daemonterminan de una forma diferente. Cuando la VM
detecta que slo permanecen en ejecucin threadDaemontermina su ejecucin.
Los daemonthreadson utilizados para ejecutar tareas auxiliares de otros threadnormales, cuando
estos han terminado aquellos no tienen funcin y finalizan.
En el ejemplo es interesante comprobar que cuando finaliza main, y la VM descubleque slo queda
el threadt , este finaliza de forma abrupta y no sale normalmente por larama finally.