Hilos en Java
Un hilo (Thread
) en Java es como una CPU virtual que pude ejecutar nuestro código Java dentro de una aplicación Java. Al iniciar una aplicación Java, se ejecuta el método main()
en el thread princiap, es un hilo especial creado por la JVM para ejecutar nuestra aplicación. Dentro de nuestra aplicación Java podemos crear e iniciar más hilos que puedan ejecutar partes del código en paralelo (de manera concurrente) con el hilo principal.
Los hilos de Java son como cualquier otro objeto de Java. Los Threads son instancias de la clase java.lang.Thread
, o instancias de subclases de esta. Además de ser objetos, los hilos de java puede ejecutar código. Ahora veremos varias formas de crear hilos en Java.
Creación e inicio de un hilo
La forma más sencilla de crear un hilo en Java es la siguiente:
1Thread thread = new Thread();
Para iniciar el hilo, se llama al método start()
del objeto Thread
:
1thread.start();
En este ejemplo no especificamos ningún código para que el hilo ejecute. Por lo tanto, el hilo se detendrá apenas haya iniciado.
Hay dos formas de especificar el código que el hilo debe ejecutar:
- Crea una subclase de Thread y sobreescribir el método
run()
. - Pasar un objeto que implemente la interfaz
Runnable
al constructor deThread
.
Subclase de Thread
La primera forma de especificar el código que se va a ejecutar, es crear una subclase de Thread
y sobreescribir el método run()
. El método run()
es lo que el hilo ejecuta cuando llamamos al método start()
. Aquí hay un ejemplo:
1class MyCustomThread extends Thread {2 public void run() {3 System.out.println("Ejecutando hilo con clase MyCustomThread");4 }5}
Para iniciar el hilo, se crea una instancia de MyCustomThread
y se llama al método start()
:
1MyCustomThread thread = new MyCustomThread();2thread.start();
La llamada desde start()
volverá apenas se haya iniciado el hilo. No esperará a que el método run()
termine de ejecutarse. El método run()
se ejecuta como si lo hiciera en una CPU diferente. Al ejecutar el método run()
, el hilo mostrará el mensaje “Ejecutando hilo con clase MyCustomThread”.
Implementación de la interfaz Runnable
La segunda forma de especificar el código que se va a ejecutar, es implementar la interfaz java.lang.Runnable
. Un objeto de Java que implementa la interfaz Runnable
puede ser ejecutado por un Thread
de Java.
La interfaz Runnable
es una interfaz estándar de Java que viene en la biblioteca estándar de Java. La interfaz Runnable
tiene un solo método, run()
, que es lo que el hilo ejecuta cuando llamamos al método start()
. Tiene el siguiente aspecto:
1public interface Runnable {2 public void run();3}
Lo que deba ejecutar el hilo al ejecutarse se debe implementar en el método run()
. Hay tres formas de implementar la interfaz Runnable
:
- Crear una clase de Java que implemente la interfaz
Runnable
. - Crear una clase anónima que implemente la interfaz
Runnable
. - Usar una expresión lambda.
La última opción la omitiremos, ya que en este curso no hemos visto expresiones lambda. Las clases anónimas, simplemente son clases que no tienen nombre. Se crean y se usan en el mismo lugar. Veremos este ejemplo luego.
Clase de Java que implementa la interfaz Runnable
La primera forma de implementar la interfaz Runnable
es crear una clase de Java que implemente la interfaz Runnable
. Aquí hay un ejemplo:
1class MyRunnable implements Runnable {2 public void run() {3 System.out.println("Ejecutando con clase MyRunnable");4 }5}
Lo único que hace esta implementación de Runnable
es mostrar un mensaje en la consola. Después de ejecutar el método run()
, el hilo se detendrá.
Clase anónima que implemente la interfaz Runnable
La segunda forma de implementar la interfaz Runnable
es crear una clase anónima que implemente la interfaz Runnable
. Aquí hay un ejemplo:
1Runnable runnable = new Runnable() {2 public void run() {3 System.out.println("Ejecutando con clase anónima");4 }5};
Aparte de ser una clase anónima, este ejemplo es muy similar al ejemplo usado en la clase que implementa la interfaz Runnable
. La única diferencia es que no se ha creado una clase con nombre. En lugar de eso, se ha creado una clase anónima que implementa la interfaz Runnable
.
Inicio de un hilo con un objeto Runnable
Para hacer que un hilo ejecute el método run()
, pasamos una instancia de una clase, o clase anónima que implemente la interfaz Runnable
a un objeto Thread
. Aquí hay un ejemplo:
1Runnable runnable = new Runnable(); // Crear una instancia de la clase que implementa la interfaz Runnable2
3Thread thread = new Thread(runnable); // Crear un hilo con el objeto Runnable4thread.start(); // Iniciar el hilo
Cuando se inicie el hilo, llamará al método run()
del objeto Runnable
en lugar de ejecutar su propio método run()
. En este caso, el hilo mostrará el mensaje “Ejecutando con clase MyRunnable”.
Error común
Al crear e iniciar un hilo, un error común es llamar al método run()
de Thread
en lugar de start()
. Aquí hay un ejemplo:
1Thread thread = new Thread(MyRunnable()); // Crear un hilo con la clase que implementa la interfaz Runnable2thread.run(); // Error
En principio no notaremos nada porque el método run()
de Runnable
se ejecuta como esperamos. Sin embargo, este NO se ejecuta en el nuevo hilo que acabamos de crear. Lo que pasa en realidad es que run()
se ejecuta en el hilo que creó el hilo. En otras palabras, el hilo principal. Por lo tanto, el mensaje “Ejecutando con clase MyRunnable” se mostrará en la consola, pero no en un hilo separado.
Para hacer que el método run()
de la instancia de MyRunnable
se ejecute en un hilo separado, debemos llamar al método start()
en lugar de run()
.