![]() | Curso JAVA |
|
www.bit.es - Calendario de cursos - Solicitud de información |
Curso
Java
Curso Analista Programador
entorno Java
Objetivos de la Unidad:
1.-
Programación modular clásica
2.-
Programación con Threads ("Hilos")
3.- Conversión de una llamada a función normal a una multithread
Supongamos que disponemos de una función denominada servicio tal como:
void servicio(String s, int a, boolean b)
{
<código de
servicio>
}
Una
llamada a la función servicio sería:
...
servicio("Hola", 5, true);
...
En este caso la línea siguiente a la llamada no se ejecutará hasta que servicio devuelva el control.
En
programación multithread podríamos escribir lo siguiente:
...
new Servicio("Hola", 5, true);
...
En este caso la línea siguiente a la llamada se
ejecutará independientemente (en paralelo) con el thread de Servicio.
La técnica para pasar de la primera forma a la segunda consiste en mapear el constructor de Thread con los mismos parámetros, de modo que la clase Servicio quedaría como sigue:
class Servicio extends Thread
{
String s;
int a;
boolean b;
Servicio(String s, int a,
boolean b)
{
this.s = s;
this.a = a;
this.b = b;
start(); // el Thread se autoarranca
}
public void run()
{
try
{
<código de servicio>
}
catch(InterruptedException e) {}
}
}
Obsérvese que run accedería a las variables miembro directamente de modo equivalente que la función servicio en que estos datos llegan como parámetros.
El método start es al comando java (ó jview) lo que run es a main
La llamada
a una función en modo clásico se puede ver como un caso de particular en el modelo
multithreaded. Basta con indicar que el Thread del programa "llamante"
se bloquee hasta que el "llamdado" no termine. Ello se consigue utilizando
el método join:
...
new Servicio("Hola", 5, true).join();
...
El método join es utilizado en aquellos casos en que se lanzan varios threads y no se quiere continuar hasta que acaben todos ellos:
Thread t1 = new ...
Thread t2 = new ...
Thread t3 = new ...
t1.join();
t2.join();
t3.join();
En
este caso hasta que no terminen los tres Threads t1, t2 y t3 el programa no pasará
la zona de joins. En cierto modo actúa como un elemento transaccional (se componen
en lógica "AND").
4.-
Herencia de Thread versus implementación de Runnable
class EjemploThread
{
public static void main(String args[])
{
// Utilizando herencia de Thread
PingPong t1= new PingPong(1000,"Ping");
PingPong t2= new PingPong(3000,"Pong");
t1.start();
t2.start();
// Implementando Runnable
PingPongr t1r= new PingPongr(1000,"Pingr");
PingPongr t2r= new PingPongr(3000,"Pongr");
t1r.t.start();
t2r.t.start();
}
}
//
// PingPong.java
//
class PingPong extends Thread
{
int interval;
String text;
PingPong(int interval0, String text0)
{
interval = interval0;
text = text0;
}
public void run()
{
try
{
for(;;)
{
System.out.println(text);
sleep(interval);
}
}
catch ( InterruptedException e )
{
return;
}
}
}
//
// PingPongr.java
//
class PingPongr implements Runnable
{
// Hay que crear el Thread
Thread t;
int Interval;
String text;
PingPongr(int Interval0,String text0)
{
// Aqui asociamos el Thread al
Objeto
t=new Thread(this);
Interval = Interval0;
text=text0;
}
public void run()
{
try
{
for(;;)
{
System.out.println(text);
// El thread es t
no la propia clase
t.sleep(Interval);
}
}
catch ( InterruptedException e)
{
return;
}
}
}
5.-
Ciclo de vida de un Thread.
...
Thread.currentThread().sleep(2000);
// el programa se detiene durante 2 segundos
...
6. Sincronización
7.- Ejemplo
/// Recurso accedido por p y c
class
Q
{
int n;
boolean valueSet = false;
synchronized int get()
{
if (!valueSet)
try {wait();} catch (InterruptedException e){}
System.out.println("Obtenido: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n)
{
if (valueSet)
try {wait();} catch (InterruptedException e){}
this.n = n;
valueSet = true;
System.out.println("Colocado: " + n); notify();
}
}
Productor
implements Runnable
{
Q q;
Thread t;
Productor(Q q)
{
this.q = q; t = new Thread(this, "Productor");
t.start();
}
public void run()
{
int i = 0;
while(true)
{
try {t.sleep(1500);} catch(Exception e){}
q.put(i++);
}
}
}
Consumidor
implements Runnable
{
Q q;
Thread t;
Consumidor(Q q)
{
this.q = q; t = new Thread(this, "Consumidor");
t.start();
}
public void run()
{
while(true)
{
try {t.sleep(1000);} catch(Exception e){}
q.get();
}
}
}
PC
{
public static void main(String args[])
{
Q q = new Q();
new Productor(q);
new Consumidor(q);
}
}
8.- Miscelánea