虚构线程简介 Java并发性的一种新方法

  • 电脑网络维修
  • 2024-11-14

作者 | Matthew Tyson

译者 | 李睿

Java19影响最深远的更新之一是引入了虚构线程。虚构线程是Project Loom的一局部,可以在Java19预览版中经常使用。

虚构线程如何上班

虚构线程在操作系统进程和运行程序级并发之间引入了一个形象层。换句话说,虚构线程可用于调度Java虚构机编排的义务,因此JVM在操作系统和程序之间起到中介作用。图1展现了虚构线程的架构。

图1.Java中虚构线程的架构

在这种架构中,运行程序实例化虚构线程,并由JVM调配处置虚构线程的计算资源。与此相比,惯例线程间接映射到操作系统(OS)进程。关于惯例线程,运行程序代码担任提供和调配操作系统资源。而经常使用虚构线程,运行程序可以实例化虚构线程,从而表白并发性的需求。但正是JVM从操作系统失掉和监禁资源。

Java中的虚构线程相似于Go言语中的goroutine。在经常使用虚构线程时,JVM只能在运行程序的虚构线程被驻留时调配计算资源,这象征着它们处于闲暇形态并期待新的事情。这种闲暇在大少数主机中是经常出现的:它们将一个线程调配给一个恳求,而后处于闲暇形态,并期待一个新的事情,例如来自数据存储的照应或来自网络的进一步输入。

经常使用传统Java线程,当主机在处置恳求时处于闲暇形态时,操作系统线程也处于闲暇形态,这重大限度了主机的可裁减性。正如NicolaiParlog所解释的那样,“操作系统不可提高平台线程的效率,但JDK经过切断其线程与操作系统线程之间的一对一相关,可以更好地利用它们。”

以前为缓解与传统Java线程相关的性能和可裁减性疑问所做的致力包括异步、照应式库(如JavaRX)。虚构线程的不同之处在于它们是在JVM级别成功的,但是它们适宜Java中现有的编程结构。

经常使用Java虚构线程:演示

在这个演示中,创立了一个经常使用Maven原型的便捷Java运行程序。为此还做了一些更改,以便在Java19预览版中启用虚构线程。一旦虚构线程被更新到预览之外,就不须要做这些更改了。

清单1显示了对Maven原型的POM文件所做的更改。须要留意的是,还将编译器设置为经常使用Java19,并在.mvn/jvm.config中增加了一行(例如清单2所示)。

清单1.演示运行程序的pom.xml

<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>19</maven.compiler.source><maven.compiler.target>19</maven.compiler.target></properties><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.10.1</version><configuration><compilerArgs><arg>--add-modules=jdk.incubator.concurrent</arg><arg>--enable-preview</arg></compilerArgs></configuration></plugin>

要使exec:java在启用预览的状况下上班,必定经常使用enable-preview开关。它经常使用所需的开关启动Maven进程。

清单2.将enable preview增加到.mvn/jvm.config

--enable-preview

如今,可以经常使用mvn compile exec:java口头该程序,虚构线程个性将被编译和口头。

经常使用虚构线程的两种方法

如今思考在代码中实践经常使用虚构线程的两种关键模式。虽然虚构线程对JVM的上班模式发生了渺小的变动,但其代码实践上与传统Java线程十分相似。设计上的相似性使得重构现有的运行程序和主机相对容易。这种兼容性还象征着用于监督和观察JVM中的线程的现有工具将与虚构线程一同上班。

Thread.startVirtualThread(Runnable r)

经常使用虚构线程的最基本方法是经常使用Thread.startVirtualThread(Runnabler))。这是实例化线程和调用thread.start()的代替方法。检查清单3中的示例代码。

清单3.实例化一个新线程

package com.infoworld;import java.util.Random;public class App {public static void main( String[] args ) {boolean vThreads = args.length > 0;System.out.println( "Using vThreads: " + vThreads);long start = System.currentTimeMillis();Random random = new Random();Runnable runnable = () -> { double i = random.nextDouble(1000) % random.nextDouble(1000);};for (int i = 0; i < 50000; i++){if (vThreads){Thread.startVirtualThread(runnable);} else {Thread t = new Thread(runnable);t.start();}}long finish = System.currentTimeMillis();long timeElapsed = finish - start;System.out.println("Run time: " + timeElapsed);}}

当带有参数运转时,清单3中的代码将经常使用一个虚构线程,否则将经常使用惯例线程。无论选用哪种线程类型,该程序都会生成5万次迭代。而后,它用随机数做一些便捷的数学运算,并跟踪口头所需的期间。

要经常使用虚构线程运转代码,须要键入:mvn-compile-exec:java-Dexec.args=“true”。要经常使用规范线程运转,须要键入:mvn-compile-exec:java。为此启动了一个极速的性能测试,失掉如下结果:

这些结果是不迷信的,但是运转时的差异是渺小的。

还有其余经常使用Thread生成虚构线程的方法,例如Thread.ofVirtual().start(runnable)。

经常使用口头器

启动虚构线程的另一种关键方法是经常使用口头器。口头器在处置线程时很经常出现,它提供了一种协调许多义务和线程池的规范方法。

虚构线程不须要经常使用线程池,由于创立和处置它们的老本很低,因此没有必要经常使用线程池。与其同样,可以将JVM看作是治理线程池。但是,许多程序确实经常使用口头器,因此Java19在口头器中蕴含了一个新的预览方法,使重构虚构线程变得容易。清单4展现了新方法和旧方法。

清单4.新的口头器方法

ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor(); // New methodExecutorService executor = Executors.newFixedThreadPool(Integer poolSize); // Old method

左右滑动检查完整代码

此外,Java19引入了Executors.newThreadPerTaskExecutor(ThreadFactorythreadFactory)方法,它可以驳回构建虚构线程的ThreadFactory。这样的线程工厂可以经过Thread.ofVirtual().factory().取得。

虚构线程的低劣通常

普通来说,由于虚构线程成功了线程类,所以它们可以在规范线程所在的任何中央经常使用。但是,在如何经常使用虚构线程以取得最佳成果方面存在差异。一个例子是在访问数据存储等资源时经常使用信号量来控制线程数量,而不是经常使用有限度的线程池。

另一个关键留意事项是,虚构线程一直守护线程,这象征着它们将使蕴含它们的JVM进程坚持优惠形态,直到它们成功。此外,不能更改它们的优先级。更改优先级和守护进程形态的方法为无操作(no-ops)。

经常使用虚构线程重构

虚构线程在实质上是一个很大的扭转,但它们很容易运行到现有的代码库中。虚构线程将对Tomcat和GlassFish等主机发生最大、最间接的影响。这样的主机应该能够以最小的致力驳回虚构线程。在这些主机上运转的运行程序将取得可裁减性的收益,而无需对代码启动任何更改,这或者对大规模运行程序发生渺小影响。思考一个运转在多个主机和外围上的Java运行程序,突然之间它将能够处置一个数量级的并发恳求,当然这齐全取决于恳求处感性能文件。

像Tomcat这样的主机准许带性能参数的虚构线程或者只是期间疑问。与此同时,假设对将主机迁徙到虚构线程感到猎奇,可以浏览CayHorstmann撰写的一篇博客文章,他在文章中展现了为虚构线程性能Tomcat的环节。他启用了虚构线程预览性能,并将Executor交流为只差一行的自定义成功。可裁减性的好处是清楚的,正如他在文章中所说:“经过这种更改,200个恳求只有3秒,而Tomcat可以轻松处置10,000个恳求。”

论断

虚构线程是JVM的一个关键变动。关于运行程序程序员来说,它们代表了异步格调编码(如经常使用回调)的另一种选用。总之,在处置Java并发性时,可以将虚构线程看作是一个摆向Java中同步编程范式的钟摆。这在编程格调上大抵相似于JavaScript引入的async/await(虽然在成功上齐全不同)。简而言之,经常使用便捷的同步语法编写正确的异步行为变得相当容易,至少在线程破费少量期间闲暇的运行程序中是这样。

原文链接:

  • 关注微信

本网站的文章部分内容可能来源于网络和网友发布,仅供大家学习与参考,如有侵权,请联系站长进行删除处理,不代表本网站立场,转载联系作者并注明出处:https://duobeib.com/diannaowangluoweixiu/4713.html

猜你喜欢

热门标签

洗手盆如何疏浚梗塞 洗手盆为何梗塞 iPhone提价霸占4G市场等于原价8折 明码箱怎样设置明码锁 苏泊尔电饭锅保修多久 长城画龙G8253YN彩电输入指令画面变暗疑问检修 彩星彩电解除童锁方法大全 三星笔记本培修点上海 液晶显示器花屏培修视频 燃气热水器不热水要素 热水器不上班经常出现3种处置方法 无氟空调跟有氟空调有什么区别 norltz燃气热水器售后电话 大连站和大连北站哪个离周水子机场近 热水器显示屏亮显示温度不加热 铁猫牌保险箱高效开锁技巧 科技助力安保无忧 创维8R80 汽修 a1265和c3182是什么管 为什么电热水器不能即热 标致空调为什么不冷 神舟培修笔记本培修 dell1420内存更新 青岛自来水公司培修热线电话 包头美的洗衣机全国各市售后服务预定热线号码2024年修缮点降级 创维42k08rd更新 空调为什么运转异响 热水器为何会漏水 该如何处置 什么是可以自己处置的 重庆华帝售后电话 波轮洗衣机荡涤价格 鼎新热水器 留意了!不是水平疑问! 马桶产生了这5个现象 方便 极速 邢台空调移机电话上门服务 扬子空调缺点代码e4是什么疑问 宏基4736zG可以装置W11吗 奥克斯空调培修官方 为什么突然空调滴水很多 乐视s40air刷机包 未联络视的提高方向 官网培修 格力空调售后电话 皇明太阳能电话 看尚X55液晶电视进入工厂形式和软件更新方法 燃气热水器缺点代码

热门资讯

关注我们

微信公众号