Java: Hilos virtuales en JDK 21
Los hilos virtuales, también conocidos como fibras o hilos verdes, son una nueva característica introducida en JDK 21 que permite a los desarrolladores crear hilos ligeros gestionados por la JVM en lugar de por el sistema operativo. Esto puede mejorar el rendimiento y la escalabilidad cuando se trabaja con un gran número de hilos.
¿Qué son los hilos virtuales?
Los hilos virtuales son similares a los hilos tradicionales en el sentido de que representan una secuencia de instrucciones que pueden ejecutarse simultáneamente con otros hilos. Sin embargo, a diferencia de los hilos tradicionales, los hilos virtuales no son programados por el sistema operativo, sino por la JVM. Esto significa que la JVM puede gestionar un gran número de hilos virtuales con mucha menos sobrecarga que los hilos tradicionales.
¿Cómo funcionan los hilos virtuales?
Los hilos virtuales se implementan utilizando continuaciones, que permiten a la JVM guardar el estado de un hilo y reanudarlo más tarde. Cuando se crea un hilo virtual, se asocia a una continuación. Cuando el hilo virtual está programado para ejecutarse, su continuación se reanuda, permitiendo que el hilo continúe ejecutándose desde donde lo dejó.
Una de las principales ventajas de los hilos virtuales es su capacidad para reducir el coste del cambio de contexto. En los hilos tradicionales, un cambio de contexto requiere que el sistema operativo guarde y restaure el estado del hilo, lo que puede ser una operación costosa. Los hilos virtuales, en cambio, son gestionados enteramente por la JVM, por lo que el cambio de contexto es mucho más rápido y menos costoso.
Otra ventaja de los hilos virtuales es su capacidad para manejar más conexiones simultáneas que los hilos tradicionales. Los hilos virtuales utilizan una técnica llamada multiplexación, que permite realizar múltiples tareas en un solo hilo. Esto significa que los hilos virtuales pueden manejar más conexiones sin necesidad de hilos adicionales, lo que puede ayudar a reducir el uso de memoria y mejorar el rendimiento de la aplicación.
Los hilos virtuales también son más fáciles de gestionar que los hilos tradicionales, ya que son gestionados por la JVM y no requieren una gestión explícita por parte del desarrollador de la aplicación. Esto puede ayudar a reducir la complejidad de las aplicaciones multihilo, haciéndolas más fáciles de desarrollar y mantener.
Ejemplo
A continuación se muestra un ejemplo de cómo crear y utilizar hilos virtuales en Java:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public clase VirtualThreadExample {
public static void main(String[] args) {
ExecutorService ejecutor = Executors.newVirtualThreadExecutor();
for (int i = 0; i < 10; i++) {
int finalI = i;
executor.submit(() -> {
System.out.println("Hola desde el hilo virtual " + finalI);
});
}
executor.shutdown();
}
}
En este ejemplo, creamos un ExecutorService utilizando el método newVirtualThreadExecutor. Esto crea un ejecutor que utiliza hilos virtuales en lugar de hilos tradicionales. A continuación, enviamos 10 tareas al ejecutor, cada una de las cuales imprime un mensaje en la consola. Cuando ejecutamos este código, vemos que cada tarea es ejecutada por un hilo virtual diferente.
El paquete java.util.concurrent incluye ahora soporte para hilos virtuales. La API LockSupport ha sido actualizada para aparcar y desaparcar hilos virtuales, permitiendo a las APIs que utilizan LockSupport, como Locks, Semaphores, y colas de bloqueo, funcionar sin problemas con hilos virtuales. Los métodos Executors.newThreadPerTaskExecutor(ThreadFactory) y Executors.newVirtualThreadPerTaskExecutor() proporcionan un ExecutorService que crea un nuevo hilo para cada tarea, facilitando la migración y la interoperabilidad con el código existente que utiliza pools de hilos y ExecutorService.
- Uso de LockSupport con hilos virtuales: En este ejemplo, creamos un hilo virtual que imprime un mensaje en la consola, luego se estaciona usando LockSupport. A continuación, pausamos el hilo principal durante 1 segundo y desestacionamos el hilo virtual, haciendo que reanude la ejecución e imprima otro mensaje en la consola.
import java.util.concurrent.locks.LockSupport;
public clase VirtualThreadExample {
public static void main(String[] args) throws InterruptedException {
Thread virtualThread = Thread.startVirtualThread(() -> {
System.out.println("Hilo virtual en ejecución");
LockSupport.park();
System.out.println("Hilo virtual reanudado");
});
Thread.sleep(1000);
LockSupport.unpark(virtualThread);
}
}
- Usando Executors.newThreadPerTaskExecutor(): En este ejemplo, creamos un ExecutorService que crea un nuevo hilo por cada tarea que se le envía. Enviamos dos tareas al ejecutor, que se ejecutan en hilos separados. A continuación, cerramos el ejecutor para liberar recursos.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public clase ThreadPerTaskExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newThreadPerTaskExecutor(r -> new Thread(r, "Hilo de Tarea"));
executor.submit() -> System.out.println("Tarea 1"));
executor.submit() -> System.out.println("Tarea 2"));
executor.shutdown();
}
}
- Usando Executors.newVirtualThreadPerTaskExecutor(): En este ejemplo, creamos un ExecutorService que crea un nuevo hilo virtual por cada tarea que se le envía. Enviamos dos tareas al ejecutor, que se ejecutan en subprocesos virtuales distintos. A continuación, cerramos el ejecutor para liberar recursos.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class VirtualThreadPerTaskExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
executor.submit() -> System.out.println("Tarea 1"));
executor.submit(() -> System.out.println("Tarea 2"));
executor.shutdown();
}
}
Conclusión
Los hilos virtuales son una nueva y potente característica de JDK 21 que permite a los desarrolladores crear hilos ligeros gestionados por la JVM en lugar de por el sistema operativo.
En general, los hilos virtuales son una nueva característica interesante en JDK 21 que ofrece muchos beneficios sobre los hilos tradicionales. Proporcionan una forma más eficiente y escalable de crear hilos en Java, y pueden ayudar a mejorar el rendimiento y la fiabilidad de las aplicaciones multihilo.