You are on page 1of 8

Hilos en Java

Procesos e Hilos
En la programacin concurrente, hay dos unidades bsicas de ejecucin: procesos
e hilos. En el lenguaje de programacin Java, la programacin concurrente est ms
relacionada con los hilos. Sin embargo, los procesos tambin son importantes.
Un Proceso es un ambiente de ejecucin autocontenido. Por lo general tiene
recursos de ejecucin completos y privados, en particular cada proceso tiene su
propio espacio de memoria.
A veces se ve a los procesos como sinnimo de programas o aplicaciones. Sin
embargo, una aplicacin puede ser un conjunto de procesos cooperativos. Para
facilitar la comunicacin entre procesos, la mayora de los sistemas operativos
soportan recursos de Comunicacin entre Procesos, IPC, como tubos y sockets.
IPC no slo se usa para comunicar procesos en un solo sistema sino procesos en
diferentes sistemas.
Un Hilo, llamado a veces proceso ligero, provee tambin un ambiente de ejecucin.
Pero crear un nuevo hilo requiere de menos recursos que crear un nuevo proceso.
Los hilos existen dentro de los procesos cada proceso tiene al menos un hilo. Un
proceso con un solo hilo tiene las siguientes propiedades:

El proceso empieza su ejecucin en un punto bien conocido. En los


programas como C, C++ o Java el proceso empieza su ejecucin en la
primera sentencia del mtodo main().
La ejecucin de las sentencias sigue una secuencia predefinida
completamente ordenada para un conjunto de entradas.
Durante la ejecucin, el proceso tiene acceso a ciertos datos. En Java hay
tres tipos de datos a los que un proceso puede acceder: variables locales que
se encuentran en la pila del hilo. Variables de instancia que se accesan
mediante referencias y variables estticas que se acceden mediante clases
o referencias a objetos.
En la figura 11.1 se ilustra un ejemplo de un sistema multitarea, en el cual hay varias
aplicaciones en ejecucin. Cada uno de ellos con un solo hilo de ejecucin. En este
caso tenemos varios procesos ejecutndose simultneamente.

ITSON Manuel Domitsu Kono

Figura 12.1
Aunque para el usuario, los procesos parecen estar ejecutndose simultneamente,
esto solo puede ocurrir en un sistema con varios procesadores o con un procesador
con varios ncleos de ejecucin. En el caso de un sistema con un solo procesador
mononcleo, la apariencia de ejecucin simultnea se logra compartiendo el
procesador entre los diferentes procesos asignndole a cada uno de ellos una
ranura de tiempo y cambiando a ejecutar otro proceso cuando el tiempo de la ranura
se ha agotado.
En un sistema multitarea que soporta multihilos, los hilos comparten los recursos de
un proceso, incluyendo la memoria y los archivos abiertos. Esto hace la
comunicacin eficiente pero potencialmente problemtica. En este caso cada
proceso puede tener uno o ms hilos. Los diferentes procesos y sus hilos pueden
ejecutarse simultneamente en forma real o aparente, dependiendo del nmero de
procesadores o ncleos.
En un proceso, los hilos mltiples tienen las siguientes propiedades:

Cada hilo empieza su ejecucin en un punto bien conocido. Para alguno de


esos hilos ese punto es la primera sentencia del mtodo main(). Para el
resto de los hilos, el programador decide ese punto al codificar el hilo.
Cada hilo ejecuta su cdigo desde su punto inicial en una forma ordenada y
predefinida para un conjunto de entradas.
Cada hilo ejecuta su cdigo independientemente de los otros hilos en el
programa. Si se requiere existen mecanismos para que los hilos cooperen
entre s.
Los hilos aparentar ejecutar con cierto grado de simultaneidad.
Los hilos tienen acceso a varios tipos de datos. Cada hilo tiene sus propias
variables locales. Los hilos pueden compartir las variables de instancia. Los
hilos comparten en forma automtica a las variables estticas.

En la figura 12.2 se ilustra un ejemplo de un sistema multitarea, en el cual hay varias


aplicaciones en ejecucin. Cada uno de ellos puede tener varios hilos de ejecucin.
En este caso, uno de esos procesos es la mquina virtual de java.

Figura 12.2
La ejecucin multihilo es una caracterstica esencial de la plataforma de Java. Cada
aplicacin tiene al menos un hilo o varias si se cuentan los hilos del sistema que
administran la memoria y el manejo de las seales. Pero desde el punto de vista del
programador se empieza con un hilo, llamado el hilo principal. Este hilo tiene la
habilidad de crear hilos adicionales como se ver ms adelante.

La API de Java para Hilos


Para comprender el funcionamiento de un programa multihilo veamos primero un
programa con un solo hilo de ejecucin. Considere el el siguiente programa formado
por dos clases:
Hilo.java
public
class
Hilo
{
public void run() {
for
(int
i
=
0;
i
System.out.println(i + ": Hola");
}
}
}

<

100;

Prueba.java
public class Prueba {
public static void main(String[] args) {

i++)

Hilo hilo = new Hilo();


hilo.run();
}
}

En la figura 12.3 se muestra el comportamiento del programa con el tiempo. En este


caso como slo hay un hilo de ejecucin las sentencias se ejecutan una despus
de la otra. No hay concurrencia.

Figura 12.3
Para hacer que el mtodo run() ejecute en paralelo con el mtodo main() y otros
mtodos de la clase Prueba, hay que modificar la clase Hilo para que sea ejecutado
por un nuevo hilo. Para ello nuestra clase Hilo deber heredar de la clase Thread.
Como se muestra en el siguiente cdigo:
Hilo.java
public class Hilo extends Thread {
public void run() {
for
(int
i
=
0;
i
<
100;
System.out.println(I + ": Hola");
}
}
}

i++)

Tambin debemos modificar a la clase que invoca a la clase Hilo para que en lugar
de invocar a su mtodo run() invoque a su mtodo start().

Prueba.java
public class Prueba {
public static void main(String[] args) {

Hilo hilo = new Hilo();


hilo.start();
}
}

El mtodo start() es quien crea otro hilo de ejecucin. Este hilo, despus de un
proceso de inicializacin invoca al mtodo run(). Este mismo hilo, cuando el
mtodo run() completa se encarga de os detalles de terminacin del hilo. El
mtodo start() del hilo original regresa inmediatamente, por lo que el mtodo
run() ejecutar en el nuevo hilo al mismo tiempo que el mtodo start() regresa
en el primer hilo como se muestra en la figura 12.4.

Figura 12.4
La clase Thread forma parte de la API de Java para hilos. Parte de esa API se
muestra en la figura 12.5.
Tabla 12.1 Atributos de la Clase Thread
public static final int MAX_PRIORITY
La mxima prioridad que puede tener un hilo
public static final int MIN_PRIORITY
La mnima prioridad que puede tener un hilo
public static final int NORM_PRIORITY
La prioridad por ausencia, que puede tener un hilo

Figura 12.4
Tabla 12.2 Mtodos de la Clase Thread.
public Thread()
public Thread(Runnable target)
public Thread(Runnable target, String name) public
Thread(String name)
Crean nuevos hilos. El parmetro target denota el objeto del cual se ejecuta el mtodo run().El
valor por omisin es null. El parmetro name establece el nombre del nuevo hilo. El valor
prestablecido es Thread-n, donde n es un entero consecutivo.
public void start()
Hace que este hilo inicie su ejecucin; La mquina virtual de Java llama al mtodo run() de este
hilo. Como resultado hay dos hilos ejecutndose concurrentemente. El hilo actual (que regresa de
la llamada al mtodo start() y el otro hilo (que ejecuta su mtodo run()).
Es ilegal iniciar un hilo ms de una vez. En particular un hilo no puede reiniciarse una vez que
completa su ejecucin.
Lanza:
IllegalThreadStateException Si el hilo ya ha sido iniciado.
public void run()

Si este hilo fue construido usando un objeto Runnable diferente, entonces se invoca al mtodo
run() del objeto. De otra forma, el mtodo no hace nada y regresa.

Hilos Usando la Interfaz Runnable


Hay ocasiones en que crear un hilo heredando de la clase Thread no es
conveniente. Por ejemplo, si la clase que deseamos que sea un hilo, es una
subclase, no podemos hacer que herede de la clase Thread ya que una clase slo
puede heredar de una clase. En estos casos, en vez de hacer que la clase herede
de la clase Thread haremos que la clase implemente la interfaz Runnable, como
se muestra en el siguiente cdigo:
HiloRunnable.java
public class HiloRunnable implements Runnable {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i + ": Hola desde la clase Hilo");
}
}
}

Una clase que implemente la interfaz debe implementar el mtodo run(). Sin
embargo para crear un nuevo hilo no es suficiente con crear una instancia de la
clase que implementa la interfaz Runnable e invocar a su mtodo start() ya
que la clase no hereda de la clase Thread y no tiene el mtodo start(). En lugar
de ello crearemos un nuevo hilo y le pasaremos al constructor de la clase Thread
la instancia de la clase que implementa la interfaz Runnable, como se muestra en
el siguiente cdigo:
PruebaHiloRunnable.java
public class PruebaHiloRunnable {
public
static
void
main(String[]
args)
Runnable hiloRunnable = new Hilo();
Thread hilo = new Thread(hiloRunnable);

hilo.start();
}
}

La razn para pasarle un objeto Runnable al constructor de la clase Thread es


para que el hilo tenga acceso al mtodo run() del objeto Runnable para que lo
ejecute. El mtodo start() del hilo llama al mtodo run() de la clase Thread
ya que no fue sobrescrito, que a su vez llama al mtodo run()del objeto Runnable
ya que el mtodo run() por ausencia de la clase Thread tiene la forma:
public void run() {
if (target != null) target.run();

Donde target es el objeto Runnable que le pasamos al constructor del hilo. As que
el hilo empieza la ejecucin de su mtodo run() quien inmediatamente llama al
mtodo run() del objeto Runnable.

Suspender y Parar un Hilo


La ejecucin de un hilo puede ser suspendida temporalmente, invocando a su mtodo
sleep(), tabla 12.3.

Tabla 12.3 Mtodos de la Clase Thread. Cont.


public static void sleep(long millis) throws InterruptedException
public static void sleep(long millis, int nanos)
throws
InterruptedException
Hace que el hilo, actualmente en ejecucin se duerma (cese temporalmente su ejecucin) por el
nmero de milisegundos (ms el nmero de nanosegundos, en el caso del segundo mtodo) dado
por el parmetro, sujeto a la precisin y exactitud de los temporalizadores y el programador tareas.
El hilo no pierde la propiedad de ninguno de sus monitores.
El valor del parmetro nanos debe estar en el rango de 0 999999 nanosegundos.
Lanza:
InterruptedException Si cualquier hilo ha interrumpido este hilo. El estado
interrumpido del hilo actual se limpia cuando se lanza esta excepcin.
IllegalArgumentException Si el valor de millis es negativo o el valor de nanos
no est en el rango de 0 999999 nanosegundos.
public final boolean isAlive()
Checa si el hilo est vivo. Un hilo est vivo si ha sido iniciado y no ha muerto.

El siguiente cdigo muestra el uso del mtodo sleep() de la clase Thread para
implementar un hilo que ejecuta una tarea peridicamente. En este ejemplo, el
mtodo suspende la ejecucin del hilo por 1000 ms por lo que el ciclo despliega el
mensaje aproximadamente cada 1 s mientras se repita el ciclo.
Este cdigo tambin ilustra la forma de parar un hilo. Para parar un hilo hay que
hacer que su mtodo run() termine su ejecucin y regrese. Para lograr eso en la
clase principal hacemos que la variable vivo tome el valor de falso, lo que har que
el ciclo termine y termine tambin el mtodo run(). Tambin en la clase principal
le asignamos a la referencia al hilo, temporizador, el valor de null para que el
recolector de basura destruya al objeto y libere los recursos que el hilo tena
asignados.

You might also like