Download 2. Especificación de Hilos en JAVA

Document related concepts
no text concepts found
Transcript
Cómputo Distribuido
JCCR ®
Especificación de Procesos en Java
Otro método para especificación de concurrencia es crear objetos Hilo explícitamente. Por
ejemplo, en Java existen una clase predefinida llamada Thread. Es posible usar herencia
para ampliar la clase Thread, sobre escribir el método run y entonces llamar al método
start() para lanzar un hilo.
Por ejemplo, un hilo que sirva para imprimir “Hello World” puede ser lanzado como se
muestra a continuación:
public class HelloWorldThread extends Thread
{
public void run()
{
System.out.println( “Hello World” );
}
public static void main(String[] args)
{
HelloWorldThread t = new HelloWorldThread();
t.start();
}
}
Interfaz Ejecutable
En el ejemplo anterior, la clase HelloWorldThread necesita heredar métodos sólo de
la clase Thread. Y ¿Qué sucede si se quiere ampliar una clase, por decir la clase Foo,
pero demás hacer que los objetos de la nueva clase se ejecuten como hilos separados?
Dado que Java no posee herencia múltiple, no es posible simplemente heredar (extends)
de la clase Foo y de la clase Thread. Para resolver este problema, Java proporciona una
interfaz llamada Runnable con el siguiente método simple:
public void run()
Para diseñar una clase ejecutable FooBar que hereda o amplia a la clase Foo, se
procederá como se muestra a continuación:
Cómputo Distribuido
JCCR ®
class Foo
{
String name;
public Foo( String s )
{
name = s; }
public void setName( String s )
{
name = s; }
public String getName()
{
return name;
}
}
class FooBar extends Foo implements Runnable
{
public FooBar( String s )
{
super(s);
}
public void run()
{
for( int i = 0; i < 10; i++ )
System.out.println( getName()+“: Hello World ”+i );
}
public static void main( String[] args )
{
FooBar f1 = new FooBar( “Romeo” );
Thread t1 = new Thread( f1 );
t1.start();
FooBar f2 = new FooBar( “Juliet” );
Thread t2 = new Thread( f2 );
t2.start();
}
}
La clase FooBar implementa la interfaz de la clase Runnable. La función main crea un
objeto ejecutable f1 de tipo FooBar. Ahora se puede crear un hilo t1 pasando al objeto
f1 como parámetro del constructor para el objeto de la clase Thread. Así este hilo
puede ser lanzado invocando al método start. Este programa crea dos hilos de la misma
manera. Cada uno de los hilos imprime una cadena obtenida usando el método
getName() heredado de la clase Foo.
Cómputo Distribuido
JCCR ®
Implementación Join en Java
Como se ha visto, es posible lanzar un hilo usando start(). El siguiente ejemplo
muestras como un hilo puede esperar por otro para finalizar su ejecución vía un
mecanismo join.
Se tiene un programa codificado en Java que calcula el n-ésimo número de Fibonacci 𝐹𝑛
usando la relación de recurrencia:
𝐹𝑛 = 𝐹𝑛−1 + 𝐹𝑛−2
Para 𝑛 ≥ 2. El caso base corresponde a:
𝐹0 = 1
y
𝐹1 = 1
Para calcular 𝐹𝑛 , le método run bifurca dos hilos que calculan 𝐹𝑛−1 y 𝐹𝑛−2
recursivamente. El hilo principal espera por estos dos hilos para terminar su cálculo
usando join. El programa completo se muestra a continuación:
public class Fibonacci extends Thread
{
int n;
int result;
public Fibonacci( int n )
{
this.n = n;
}
public void run()
{
if( n == 0 || n == 1 )
result = 1;
else
{
Fibonacci f1 = new Fibonacci( n-1 );
Fibonacci f2 = new Fibonacci( n-2 );
f1.start();
f2.start();
try{
f1.join();
f2.join();
}catch( InterruptedException e ){};
result = f1.getResult() + f2.getResult();
}
}
Cómputo Distribuido
JCCR ®
public int getResult()
{
return result;
}
public static void main( String[] args )
{
Fibonacci f1 = new Fibonacci( Ingeger.parseInt( args[0] ) );
f1.start();
try{
f1.join();
}catch( InterruptedException e ){};
System.out.println( “Answer is ” + f1.getResult() );
}
}
Planificador de Hilos
En el ejemplo de la clase FooBar, se tienen 2 hilos. El mismo programa en Java trabajará
con una máquina de un solo CPU tan bien como en una máquina con multi-procesador. En
una máquina con un solo CPU, si ambos hilos son ejecutables, ¿Cuál sería seleccionado
por el sistema para ser ejecutado? La respuesta depende de la prioridad y las reglas de
planificación (scheduling) del sistema.
El programador puede cambiar la prioridad de los hilos usando los métodos
setPriority y se obtiene la prioridad actual con getPriority. Las constantes
enteras definidas en la clase Thread son MIN_PRIORITY y MAX_PRIORITY. Por
defecto, un hilo tiene la prioridad NORM_PRIORITY.
Un hilo en Java que se está ejecutando puede ser bloqueado mediante un llamado a
sleep, wait, o cualquier función de sistema que sirva para bloquear. Cuando esto
sucede, un hilo ejecutable con la prioridad más alta es seleccionado para ser ejecutado.
Cuando un hilo con prioridad alta está siendo ejecutado, éste puede ser suspendido
cuando su intervalo de tiempo se agotó. Así se permite que otro proceso con el mismo
nivel de prioridad sea ejecutado.