Java 19: Virtual threads

Ejemplo práctico de uso de virtual threads en Java 19 y Maven

Los virtual threads (hilos virtuales) son una nueva característica de Java que aborda las limitaciones en el modelo de concurrencia tradicional de Java. Permiten crear y administrar múltiples subprocesos de manera más sencilla y eficiente, logrando menos sobrecarga de memoria y cpu. Se introdujeron en Java 16 y están disponibles en versiones posteriores.

Un virtual thread es un subproceso que se ejecuta en una estructura de datos ligera llamada "task" dentro de la JVM, en lugar de thread físico del sistema operativo. Esto permite que el programa pueda crear y gestionar un gran número de subprocesos de manera más eficiente, ya que no requiere la asignación de un espacio de memoria para cada thread físico. Los virtual threads son útiles para escenarios en los que se necesitan muchos subprocesos para realizar trabajos cortos y sincronizados, como en aplicaciones de red y en servidores. Además, los virtual threads pueden mejorar el rendimiento en aplicaciones que utilizan subprocesos de forma intensiva y pueden simplificar la programación concurrente en algunos casos.

La eliminación de la participación del sistema operativo en el ciclo de vida de un subproceso virtual es lo que elimina el cuello de botella de escalabilidad. Con esto, hay una reducción drástica de los requisitos de recursos para manejar múltiples procesos en competencia, dando como resultado un mayor rendimiento para los servidores.

Ejemplo de código:

Primero, configuramos un complemento en maven en la sección de compilación, especificando la version de Java y la habilitación de las nuevas características del lenguaje:

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>19</source>
                    <target>19</target>
                    <compilerArgs>
                        <arg>--enable-preview</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>

Método con implementación tradicional de Java: se generan 50.000 threads y cada 10.000 se imprime el numero del proceso actual.


    public void platformThreads() {

        System.out.println("platform threads");
        final Instant start = Instant.now();

        for (int i =0; i < 50_000; i++) {
            if (i % 10_000 == 0) {
                System.out.println(i);
            }
            new Thread( () -> {
                try {
                    Thread.sleep(5_000);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }).start();
        }
        printElapsedTime( Duration.between( start, Instant.now()) );
    }

    private void printElapsedTime(Duration duration) {
        long seconds = duration.getSeconds() % 60;
        long millis = duration.toMillis() % 60;
        System.out.println( String.format("Time: %d seconds, %d milliseconds", seconds, millis) );
    }

Salida de terminal: colapsa el proceso por falta de recursos..

terminal-capture

Método con la nueva implementación de Java, utilizando los virtual threads: se generan 50.000 threads y cada 10.000 se imprime el número del proceso actual.

public void virtualThreads() {

        System.out.println("virtual threads");
        final Instant start = Instant.now();

        for (int i =0; i < 50_000; i++) {
            if (i % 10_000 == 0) {
                System.out.println(i);
            }
            Thread.startVirtualThread (() -> {
                try {
                    Thread.sleep(5_000);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            });
        }

        printElapsedTime( Duration.between( start, Instant.now()) );
    }

Salida en terminal, el proceso tarda 9 milesegundos:

terminal-capture

Puedes descargar el código fuente completo de este ejemplo desde el siguiente enlace: virtual threads example.




¿Tienes alguna consulta?
Puedes contactarme enviándome un mensaje desde aquí.