jueves, 8 de marzo de 2012

4.3 CREACIÓN Y CONTROL DE HILOS

INSTITUTO TECNOLÓGICO DE CERRO AZUL



PRESENTAN:


Ø  Flores Ordóñez Lei Lani
 Ø  González Hernández Carlos Arturo
Ø  Hernández Gabriel Juan Carlos
Ø Rodríguez Jalife Yael   
Ø  Santiago de la Cruz Martin Fco.


MATERIA:

Tópicos Avanzados de Programación


PROFESOR:

Lic. Ma. Alejandra Rosas Toro






Creación y Control de Hilos

En Java, los hilos comparten el mismo espacio de memoria. Incluso comparten gran parte del  entorno de ejecución, de modo que la creación de nuevos hilos es mucho más rápida que la creación de nuevos procesos. La ventaja que proporcionan los hilos es la capacidad de tener más de un camino de ejecución en un mismo programa. Así, con un único proceso, ejecutándose una JVM (Java Virtual Machine), habrá siempre más de un hilo, cada uno con su propio camino de ejecución.

En cuanto al proceso de creación de hilos, son dos los mecanismos que nos permiten llevarlo a cabo en Java: implementando la interfaz Runnable, o extendiendo la clase Thread,esto es, creando una subclase de esta clase.

Lo más habitual es crear hilos implementando la interfaz Runnable, dado que las interfaces representan una forma de encapsulamiento del trabajo que una clase debe realizar.

Así, se utilizan para el diseño de requisitos comunes a todas las clases que se tiene previsto implementar. La interfaz define el trabajo, la funcionalidad que debe cubrirse, mientras que la clase o clases que implementan la interfaz realizan dicho trabajo (cumplen esa funcionalidad). 

Todas las clases o grupos de clases que implementen una cierta interfaz deberán seguir las mismas reglas de funcionamiento.

El otro mecanismo de creación de hilos, como ya hemos dicho, consistiría en la creación previa de una subclase de la clase Thread, la cual podríamos instanciar después.

Por ejemplo:

class MiThread extends Thread {
public void run() {
. . .
}
}

Se corresponde con la declaración de un clase, MiThread, que extiende la clase Thread, sobrecargando el método Thread.run heredado con su propia implementación.


Es en el método run donde se implementa el código correspondiente a la acción (la tarea)  que el hilo debe desarrollar . El método run no es invocado directa o explícitamente (a menos  que no quieras que se ejecute dentro de su propio hilo). En lugar de esto, los hilos se arrancan con el método start, se suspenden con el método suspend, se reanudan con el método resume, y se detienen con el método stop (el cual supone también la muerte del hilo y la correspondiente excepción Thread Death?), como ya explicaremos en el apartado de Estado y Control de Hilos. Un hilo suspendido puede reanudarse en la instrucción del método run en la que fue suspendido.

En el caso de crear un hilo extendiendo la clase Thread, se pueden heredar los métodos y  variables de la clase padre. Si es así, una misma subclase solamente puede extender o derivar una vez de la clase padre Thread. Esta limitación de Java puede ser superada a través de la implementación de Runnable. Veamos el siguiente ejemplo:

public class Mi Thread implements Runnable {
Thread t;
public void run() {
// Ejecución del thread una vez creado
}
}

En este caso necesitamos crear una instancia de Thread antes de que el sistema pueda ejecutar el proceso como un hilo. Además, el método abstracto run que está definido en la interfaz Runnable tiene que implementarse en la nueva clase creada.

La diferencia entre ambos métodos de creación de hilos en Java radica en la flexibilidad con que cuenta el programador, que es mayor en el caso de la utilización de la interfaz Runnable.

Sobre la base del ejemplo anterior, se podría extender la clase Mi Thread a continuación, si fuese necesario. La mayoría de las clases creadas que necesiten ejecutarse como un hilo implementarán la interfaz Runnable, ya que así queda cubierta la posibilidad de que sean extendidas por otras clases.

Por otro lado, es un error pensar que la interfaz Runnable está realizando alguna tarea mientras un hilo de alguna clase que la implemente se está ejecutando. Es una interfaz, y como tal, sólo contiene funciones abstractas (concretamente una única, run), proporcionando tan solo una idea de diseño, de infraestructura, de la clase Thread, pero ninguna funcionalidad. Su declaración en Java tiene el siguiente aspecto:

package Java.lang;
public interfaz Runnable {
public abstract void run() ;
}

Comentados los aspectos más importantes de la interfaz Runnable, veamos ahora la definición de la clase Thread, de la cual podemos deducir lo que realmente se está haciendo:

public class Thread implements Runnable {
public void run() {
Java Threads (Hilos en Java)
6
if( tarea != null )
tarea.run() ;
}

}

Se deduce, por tanto, que la propia clase Thread de Java también implementa la interfaz Runnable. Observamos que en el método run de Thread se comprueba si la clase con que se está trabajando en ese momento (tarea), que es la clase que se pretende ejecutar como hilo,es o no nula. En caso de no ser nula, se invoca al método run propio de dicha clase.


Control de un hilo

Arranque de un hilo

En el contexto de las aplicaciones, sabemos que es main la primera función que se invoca tras  arrancar, y por tanto, lógicamente, es el lugar más apropiado para crear y arrancar otros hilos.

La línea de código:

t1 = new Test Th?( “Thread 1″,(int)(Math.random()*2000) );

Siendo Test Th una subclase de la clase Thread (o una clase que implemente la interfaz Runnable) crea un nuevo hilo. Los dos argumentos pasados, sin mayor relevancia, satisfarán el prototipo del constructor de la clase y se utilizarán para la inicialización del objeto.

Al tener control directo sobre los hilos, tenemos que arrancarlos explícitamente. Como ya se comentó anteriormente, es la función miembro start la que nos permite hacerlo. En nuestro ejemplo sería:

t1.start();

start, en realidad es un método oculto en el hilo que llama al método run.


Manipulación de un hilo

Si todo fue bien en la creación del objeto Test Th (t1), éste debería contener un hilo, una traza de ejecución válida, que controlaremos en el método run del objeto.

El cuerpo de esta función miembro viene a ser el cuerpo de un programa como ya los conocemos. Digamos que es la rutina main a nivel de hilo. Todo lo que queremos que haga el hilo debe estar dentro del método run. Cuando finalice run, finalizará también el hilo que lo ejecutaba.


Suspensión de un Hilo

La función miembro suspend de la clase Thread permite tener un control sobre el hilo de modo que podamos desactivarlo, detener su actividad durante un intervalo de tiempo indeterminado, a diferencia del uso de la llamada al sistema sleep, que simplemente lleva al hilo a un estado de “dormido”, y siempre durante un número de milisegundos concreto.

Este método puede resultar útil si, construyendo un applet con un hilo de animación,queremos permitir al usuario detener (que no finalizar) la animación, hasta que éste decida reanudarla.

Este método no detiene la ejecución permanentemente. El hilo es suspendido indefinidamente y para volver a activarlo de nuevo necesitamos realizar una invocación a la función miembro resume.


Parada de un Hilo

Ya conocemos los métodos de control de hilos que nos permiten arrancarlos, suspenderlos y reanudarlos. El último elemento de control que se necesita sobre hilos es el método stop, utilizado para terminar la ejecución de un hilo de forma permanente:

t1.stop();

Señalar que esta llamada no destruye el hilo, sino que detiene su ejecución, y ésta no puede reanudarse con el método start. Cuando se desasignen las variables que se usan en el hilo, el objeto hilo (creado con new) quedará marcado para eliminarlo y el garbage collector (recolector de basura de Java) se encargará de liberar la memoria que utilizaba.

Tiene sentido su utilidad, por ejemplo, en aplicaciones complejas que necesiten un control sobre cada uno de los hilos que se lancen.

Por último, un método de control de hilos que nos permite comprobar si una instancia está viva (el hilo se ha arrancado y aún no se ha detenido) o no (bien no se arrancó; bien ya finalizó).

Estamos hablando de la función miembro isAlive.

t1.isAlive();

Devolverá true en caso de que el hilo t1 esté vivo, es decir, ya se haya llamado a su método run y no haya sido parado con un stop ni haya terminado el método run en su ejecución. En otro caso, lógicamente, devolverá false.

Ejemplo:




Fuente:

No hay comentarios:

Publicar un comentario