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.