La función de subprocesos virtuales (corutina) de Java abre la etapa de vista previa, y la dificultad del desarrollo de subprocesos múltiples se reducirá en gran medida.

La alta concurrencia y los subprocesos múltiples siempre han sido puntos difíciles en la programación de Java , y también son los puntos principales de las preguntas de las entrevistas. Los desarrolladores de Java también han estado tratando de utilizar subprocesos múltiples para resolver problemas de simultaneidad del servidor de aplicaciones. Pero los subprocesos múltiples no son fáciles, por lo que ha aparecido una nueva tecnología, que es el subproceso virtual.

Puntos débiles del multihilo tradicional

Pero no es fácil escribir código de subprocesos múltiples. La secuencia de ejecución que es difícil de controlar, la seguridad de los subprocesos de las variables compartidas, la observabilidad de las excepciones, etc., son todas dificultades en la programación de subprocesos múltiples.

Si cada solicitud se procesa en un subproceso durante la duración de la solicitud, para aumentar el rendimiento de la aplicación, la cantidad de subprocesos debe crecer con el rendimiento. Desafortunadamente, los subprocesos son un recurso escaso, crear un subproceso es costoso, incluso la introducción de la agrupación no puede reducir el costo de crear nuevos subprocesos, y la implementación actual de subprocesos de JDK limita el rendimiento de la aplicación muy por debajo del nivel de hardware que puede admitirse.

Por esta razón, muchos desarrolladores recurren a la programación asíncrona, como CompletableFuturelos marcos reactivos que están de moda ahora. Pero estas técnicas no pueden escapar del "infierno de devolución de llamada" o carecen de observabilidad.

Para resolver estos puntos débiles y mejorar la armonía de la plataforma Java, se ha vuelto necesario implementar un estilo de subproceso por solicitud para cada solicitud. ¿Es posible implementar un subproceso virtual de "bajo costo" para asignar al subproceso del sistema para reducir la operación directa del subproceso del sistema? ¡Las ideas deberían estar bien! Entonces, la comunidad Java lanzó la propuesta JEP 425 sobre subprocesos virtuales.

hilo virtual

Los subprocesos virtuales ( virtual threads ) deberían ser muy económicos y pueden crearse sin preocuparse por los recursos de hardware del sistema, y ​​no deben agruparse. Se debe crear un nuevo subproceso virtual para cada tarea de la aplicación. Por lo tanto, la mayoría de los subprocesos virtuales serán de corta duración y tendrán pilas de llamadas poco profundas, realizando solo una llamada de cliente HTTP de tarea única o una consulta JDBC única . Los subprocesos de plataforma correspondientes (Platform Threads, que ahora son subprocesos JVM tradicionales) son pesados ​​y costosos, por lo que generalmente deben agruparse. Tienden a ser de larga duración, tienen pilas de llamadas profundas y se comparten entre muchas tareas.

En resumen, los subprocesos virtuales conservan un estilo confiable e independiente de subprocesos por solicitud que es compatible con el diseño de la plataforma Java, al tiempo que optimiza la utilización del hardware. El uso de subprocesos virtuales no requiere aprender nuevos conceptos, ni siquiera cambiar el hábito de operar con subprocesos múltiples, utilizando una API más accesible , compatible con diseños anteriores de subprocesos múltiples, y no afecta en absoluto la escalabilidad del código.

La diferencia entre subprocesos de plataforma y subprocesos virtuales

Para comprender mejor este diseño, el borrador compara los dos subprocesos.

hilo actual

Cada uno java.lang.Threades ahora un subproceso de plataforma que ejecuta código Java en el subproceso del sistema operativo subyacente y captura el subproceso del sistema operativo durante la vida útil del código. La cantidad de subprocesos de la plataforma está limitada por la cantidad de subprocesos del sistema operativo.

Los hilos de la plataforma no salen de la etapa de la historia uniéndose a los hilos virtuales.

futuros hilos virtuales

Los subprocesos virtuales son implementaciones ligeras de subprocesos proporcionados por el JDK en lugar del sistema operativo. Son una forma de subprocesos en modo usuario que han tenido éxito en otros lenguajes de subprocesos múltiples (como las corrutinas en Golang y los procesos en Erlang). Los subprocesos virtuales emplean la programación M:N, donde un gran número (M) de subprocesos virtuales están programados para ejecutarse en un número menor (N) de subprocesos del sistema operativo. El planificador de subprocesos virtuales de JDK es un ForkJoinPoolmecanismo de robo de trabajo que funciona en modo FIFO.

我们可以很随意地创建10000个虚拟线程:

// 预览代码
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10_000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
}  
复制代码

无需担心硬件资源是否扛得住,反过来如果你使用Executors.newCachedThreadPool()创建10000个平台线程,在大多数操作系统上很容易因资源不足而崩溃。

为吞吐量而设计

但是这里依然要说明一点,虚拟线程并是为了提升执行速度而设计。它并不比平台线程速度快,它们的存在是为了提供规模(更高的吞吐量),而不是速度(更低的延迟)。它们的数量可能比平台线程多得多,因此根据利特尔定律,它们可以实现更高吞吐量所需的更高并发性。

换句话说,虚拟线程可以显着提高应用程序吞吐量

  • 并发任务的数量很高(超过几千个)。

  • 工作负载不受 CPU 限制,因为在这种情况下,拥有比处理器内核多得多的线程并不能提高吞吐量。

虚拟线程有助于提高传统服务器应用程序的吞吐量,正是因为此类应用程序包含大量并发任务,这些任务花费大量的时间等待。

增强可观测性

编写清晰的代码并不是全部。对正在运行的程序状态的清晰表示对于故障排除、维护和优化也很重要,JDK 长期以来一直提供调试、分析和监视线程的机制。 在虚拟线程中也会增强代码的可观测性,让开发人员更好地调试代码。

新的线程API

为此增加了新的线程API设计,目前放出的部分如下:

  • Thread.Builder 线程构建器。

  • ThreadFactory 能批量构建相同特性的线程工厂。

  • Thread.ofVirtual() 创建一个虚拟线程。

  • Thread.ofPlatform() 创建一个平台线程。

  • Thread.startVirtualThread(Runnable) 一种创建然后启动虚拟线程的便捷方式。

  • Thread.isVirtual() 测试线程是否是虚拟线程。

还有很多就不一一演示了,有兴趣的自行去看JEP425

总结

Todavía hay muchos detalles en JEP425 Basado en mi falta de comprensión personal, solo puedo interpretar tanto. Las corrutinas se han mencionado en la comunidad de Java durante mucho tiempo y ahora finalmente hay acción real, lo cual es una noticia emocionante. Sin embargo, todavía hay muchas cosas involucradas en esta función, incluida la compatibilidad de los subprocesos de la plataforma, ThreadLocalalgunas influencias en ella y la influencia en JUC . Es posible que se necesiten varias vistas previas para finalmente aterrizar. Es posible que el hermano gordo no pueda ponerse al día con ese tiempo, pero muchos compañeros de clase jóvenes deberían poder ponerse al día.

关注公众号:Felordcn获取更多资讯

Blog personal: https://felord.cn

Supongo que te gusta

Origin juejin.im/post/7084059065475104775
Recomendado
Clasificación