Saltearse al contenido

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:

1
Thread thread = new Thread();

Para iniciar el hilo, se llama al método start() del objeto Thread:

1
thread.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:

  1. Crea una subclase de Thread y sobreescribir el método run().
  2. Pasar un objeto que implemente la interfaz Runnable al constructor de Thread.

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:

1
class 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():

1
MyCustomThread thread = new MyCustomThread();
2
thread.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:

1
public 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:

  1. Crear una clase de Java que implemente la interfaz Runnable.
  2. Crear una clase anónima que implemente la interfaz Runnable.
  3. 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:

1
class 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:

1
Runnable 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:

1
Runnable runnable = new Runnable(); // Crear una instancia de la clase que implementa la interfaz Runnable
2
3
Thread thread = new Thread(runnable); // Crear un hilo con el objeto Runnable
4
thread.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:

1
Thread thread = new Thread(MyRunnable()); // Crear un hilo con la clase que implementa la interfaz Runnable
2
thread.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().