Para hablar de hilos en Java primeramente se necesita entender lo que es un hilo. Un hilo es un proceso que se está ejecutando en un momento determinado en nuestro sistema operativo, como cualquier otra tarea, esto se realiza directamente en el procesador. Existen los llamados 'demonios' que son los procesos que define el sistema en sí para poder funcionar y otros que llamaremos los hilos definidos por el usuario o por el programador, estos últimos son procesos a los que el programador define un comportamiento e inicia en un momento específico.
En Java, el proceso que siempre se ejecuta es el llamado main que es a partir del cual se inicia prácticamente todo el comportamiento de nuestra aplicación, y en ocasiones a la aplicación le basta con este solo proceso para funcionar de manera adecuada, sin embargo, existen algunas aplicaciones que requieren más de un proceso (o hilo) ejecutándose al mismo tiempo (multithreading), por ejemplo, se tiene una aplicación de una tienda departamental de la cual se actualizan los precios y mercancías varias veces al día a través de la red, se verifícan los nuevos descuentos y demás pero que a su vez es la encargada de registrar las compras y todos movimientos que se realice con la mercancía dentro de la tienda, si se decide que dicha aplicación trabajará de la manera simple y con un solo proceso (o hilo), el trabajo de la actualización de precios y mercancías debe de finalizar antes de que alguien pueda hacer algún movimiento con un producto dentro de la tienda, o viceversa, ya que la aplicación no es capaz de mantener el proceso de actualización en segundo plano mientras se registra un movimiento. Si se toma este modelo mono-hilo el tiempo y dinero que se perderá dentro de la tienda será muchísimo mayor comparando con un modelo multi-hilo. En un modelo multi-hilo se pueden realizar todas las actualizaciones en segundo plano mientras se registra una o más ventas o movimientos, cada proceso independiente del otro viviendo o ejecutándose al mismo tiempo dentro de la misma aplicación.
Al hablar de multi-hilo pudiera parecer que necesitamos más de un procesador para realizar dichas tareas pero no es así, el procesador mismo junto con la máquina virtual de Java gestionan el flujo de trabajo y dan la impresión de que se puede ejecutar más de algún proceso al mismo tiempo (aunque en términos estrictos eso no es posible), de cualquier manera no ahondaré en el funcionamiento del procesador, basta con entender que en Java, 2 o más procesos pueden ejecutarse al mismo tiempo dentro de una misma aplicación y para ello son necesarios los Threads o hilos.
Ahora que ya entendemos lo que son los hilos pasaremos a una definición un poco más específica de Java. En Java un hilo o Thread puede ser 2 cosas:
+ Una instancia de la clase
java.lang.Thread
+ Un proceso en ejecución
Una instancia de la clase java.lang.Thread, no es más que cualquier otro objeto, con variables y métodos predefinidos. Un proceso en ejecución es un proceso individual que realiza una tarea o trabajo, tiene su propia pila de información independiente a la de la aplicación principal.
Es necesario entender que el comportamiento de los hilos o threads varía de acuerdo a la máquina virtual, incluso el concepto más importante a entender con los hilos en Java es que...
"Cuando se trata de hilos, muy pocas cosas está garantizadas"
...por ello se debe ser cautelosos al momento de interpretar el comportamiento de un hilo. Pasemos al código.
Crear un hilo (Thread)::
Un hilo o proceso en Java comienza con una instancia de la clase java.lang.Thread, si analizamos la estructura de dicha clase podremos encontrar bastantes métodos que nos ayudan a controlar el comportamiento de los hilos, desde crear un hilo, iniciarlo, pausar su ejecución, etc. Aquellos métodos que siempre tenemos que tener presentes con respecto a los hilos son:
- start()
- yield()
- sleep()
- run()
La acción sucede dentro del método run(), digamos que el código que se encuentra dentro de dicho método es el trabajo por hacer, por lo tanto, si queremos realizar diversas operaciones cada una simultánea pero de manera independiente, tendremos varias clases, cada una con su respectivo método run(). Dentro del método run() puede haber llamados a otros métodos como en cualquier otro método común, pero la pila de ejecución del nuevo proceso siempre comenzará a partir de la llamada al método run().
Definir un nuevo hilo::
Para definir e instanciar un nuevo Thread (hilo, proceso) existen 2 formas:
+ Extendiendo (o heredando) a la clase
java.lang.Thread
+ Implementando la interfaz
Runnable
Normalmente en el trabajo diario es más recomendable el implementar la interfaz Runnable, en lugar de extender la clase java.lang.Thread debido a que una clase solamente puede heredar o extender otra sola clase pero puede implementar muchas interfaces. Si extendemos de la clase java.lang.Thread no podremos extender o heredar ninguna otra, pero si implementamos la interfaz Runnable, podremos heredar cualquier otra clase e implementar muchas otras interfaces sin perder el comportamiento de la nuestra.
En cualquiera de los 2 casos, ya sea heredando de java.lang.Thread o implementando Runnable, al definir e instanciar un nuevo hilo, necesitaremos de redefinir el método run(), veamos cómo hacerlo.
Extendiendo java.lang.Thread::
1.- Hereda a la clase java.lang.Thread por medio de la palabra '
extends'.
2.- Redefine el método
run().
P. ej.
class MiHilo extends Thread{
public void run(){
System.out.println("Trabajo por hacer dentro de MiHilo");
}
}
Nuevamente, esto no es recomendable ya que al heredar la clase Thread, no podrás heredar nada más.
Toma en cuenta que puedes sobrecargar el método run() sin ningún problema como se muestra a continuación...
class MiHilo extends Thread{
public void run(){
System.out.println("Trabajo por hacer dentro de MiHilo");
}
public void run(String s){
System.out.println("La cadena ingresada es " + s);
}
}
...sin embargo, al realizar esto, no estarás utilizando tu nuevo método public void run (String s) en un proceso separado, es un simple método común y corriente como cualquier otro que tienes que mandar llamar de manera independiente ya que los hilos trabajan con un método run() sin argumentos.
Implementando la interfaz Runnable::
1.- Implementa a la interfaz Runnable por medio de la palabra '
implements'.
2.- Redefine el método
run().
P. ej.
class MiHilo implements Runnable{
public void run(){
System.out.println("Trabajo por hacer dentro de MiHilo");
}
}
Independientemente de cómo definas tu hilo (por medio de extends Thread o implements Runnable), el hilo tendrá el mismo comportamiento.
Instanciando un hilo o Thread::
Debemos recordar que cada hilo de ejecución es una instancia de la clase Thread, independientemente de si tu método run() está dentro de una subclase de Thread o en una implementación de la interfaz Runnable, se necesita un objeto tipo Thread para realizar el trabajo.
Si has extendido la clase Thread, el instanciar el hilo es realmente simple:
MiHilo h = new MiHilo();
Si has implementado la interfaz Runnable, es un poquito más complicado, pero solo un poco:
MiHilo h = new MiHilo();
Thread t = new Thread(h); // Pasas tu implementación de Runnable al nuevo Thread
Puedes pasar una misma instancia de una clase que implementa Runnable a diversos objetos de tipo Thread...
public class PruebaHilos{
public static void main (String[] args)
{
MiHilo h = new MiHilo();
Thread t1 = new Thread(h);
Thread t2 = new Thread(h);
Thread t3 = new Thread(h);
}
}
El pasar un solo objeto tipo MiHilo a varios objetos tipo Thread significa que el trabajo que se encuentra dentro del método run() de MiHilo se realizará en diversas ocasiones, o lo que es lo mismo, varios hilos realizarán el mismo trabajo.
Hasta aquí le dejamos con la primera parte...
Más sobre programación en Java
aquí.
Despues de esto me han quedado dudas el primer metodo heredar de la clase thread no sirve entonces ya que nadamas puedo usarlo una vez y quisiera saber un ejemplo aplicativo es decir algo que pueda servirme realmente.