项目织机

为什么为什么?

Java 8流背后的驱动程序之一是并发编程。 在流管道中,指定要完成的工作,然后任务将自动分发到可用处理器上:

var result = myData.parallelStream().map(someBusyOperation).reduce(someAssociativeBinOp).orElse(someDefault);

当数据结构便宜且可拆分为多个部分且操作使处理器繁忙时,并行流将发挥出色的作用。 这就是它的设计目的。

但是,如果您的工作负载包含大部分阻塞的任务,那么这对您没有帮助。 那是您的典型Web应用程序,可以处理许多请求,每个请求都花费大量时间等待REST服务,数据库查询等结果。

1998年,令人惊奇的是,Sun Java Web Server(Tomcat的前身)在单独的线程而不是OS进程中运行了每个请求。 这样就可以满足数千个并发请求! 如今,这并不令人惊讶。 每个线程占用大量内存,典型服务器上不能拥有数百万个线程。

这就是为什么服务器端编程的现代口号是:“永不阻塞!” 相反,您指定一旦数据可用就应该发生什么。

这种异步编程风格非常适合服务器,使它们可以轻松支持数百万个并发请求。 对于程序员来说不是那么好。

这是使用HttpClient API的异步请求:

HttpClient.newBuilder().build().sendAsync(request, HttpResponse.BodyHandlers.ofString()).thenAccept(response -> . . .);.thenApply(. . .);.exceptionally(. . .);

我们通常用语句实现的功能现在被编码为方法调用。 如果我们喜欢这种编程风格,就不会在Lisp中使用我们的编程语言来编写语句和编写快乐的代码。

诸如JavaScript和Kotlin之类的语言为我们提供了“异步”方法,在这些方法中,我们编写语句,然后将这些语句转换为您刚刚看到的方法调用。 很好,只不过它意味着现在有两种方法-常规方法和转换方法。 而且您不能混合使用它们(“红色药丸/蓝色药丸”的分界)。

Project Loom从Erlang和Go等语言中获得指导,在这些语言中,阻塞并不是什么大问题。 您可以在“光纤”或“轻型线程”或“虚拟线程”中运行任务。 该名称尚待讨论,但我更喜欢“光纤”,因为它很好地表示了多个光纤在一个载波线程中执行的事实。 当发生阻塞操作(例如等待锁定或I / O)时,光纤将停放。 停车比较便宜。 如果很多时候都停放了一根承载线,则可以支撑一千根光纤。

请记住,Project Loom不能解决所有并发问题。 如果您有大量计算任务并且想让所有处理器内核都忙,它对您无济于事。 它对于使用单个线程的用户界面没有帮助(用于序列化对不是线程安全的数据结构的访问)。 在该用例中继续使用AsyncTask / SwingWorker / JavaFX Task 。 当您有很多任务花费大量时间阻塞时,Project Loom很有用。

注意 如果您已经存在很长时间了,您可能还记得早期的Java版本具有映射到OS线程的“绿色线程”。 但是,有一个关键的区别。 当绿色线程被阻塞时,其承载线程也被阻塞,从而阻止了同一承载线程上的所有其他绿色线程取得进展。

踢轮胎

在这一点上,Project Loom仍处于探索阶段。 API会不断变化,因此在假期过后尝试使用该代码时,请准备好适应最新的API版本。

您可以从http://jdk.java.net/loom/下载Project Loom的二进制文件,但是它们很少更新。 但是,在Linux机器或VM上,自己构建最新版本很容易:

git clone https://github.com/openjdk/loom
cd loom 
git checkout fibers
sh configure  
make images

根据您已经安装的内容, configure可能会失败一些,但是消息会告诉您需要安装哪些软件包才能继续进行。

在API的当前版本中,光纤或现在称为虚拟线程的虚拟线程表示为Thread类的对象。 这是三种生产纤维的方法。 首先,有一个新的工厂方法可以构造OS线程或虚拟线程:

Thread thread = Thread.newThread(taskname, Thread.VIRTUAL, runnable);

如果您需要更多自定义,则有一个构建器API:

Thread thread = Thread.builder().name(taskname).virtual().priority(Thread.MAX_PRIORITY).task(runnable).build();

但是,一段时间以来,手动创建线程一直被认为是较差的做法,因此您可能不应该执行任何一种操作。 而是将执行程序与线程工厂一起使用:

ThreadFactory factory = Thread.builder().virtual().factory();
ExecutorService exec = Executors.newFixedThreadPool(NTASKS, factory);

现在,熟悉的固定线程池将以与以往相同的方式从工厂调度虚拟线程。 当然,还将有OS级别的载体线程来运行这些虚拟线程,但这是虚拟线程实现的内部。

固定线程池将限制并发虚拟线程的总数。 默认情况下,从虚拟线程到载体线程的映射是通过使用系统属性jdk.defaultScheduler.parallelism或默认情况下Runtime.getRuntime().availableProcessors()所给定数量的内核的jdk.defaultScheduler.parallelism池完成的。 您可以在线程工厂中提供自己的调度程序:

factory = Thread.builder().virtual().scheduler(myExecutor).factory();

我不知道这是否是人们想要做的。 为什么载具线程多于核心?

返回我们的执行人服务。 您可以在虚拟线程上执行任务,就像在OS级线程上执行任务时一样:

for (int i = 1; i <= NTASKS; i++) {String taskname = "task-" + i;exec.submit(() -> run(taskname));
}
exec.shutdown();
exec.awaitTermination(delay, TimeUnit.MILLISECONDS);

作为一个简单的测试,我们可以在每个任务中入睡。

public static int DELAY = 10_000;public static void run(Object obj) {try {Thread.sleep((int) (DELAY * Math.random()));} catch (InterruptedException ex) {ex.printStackTrace();}System.out.println(obj);}

如果现在将NTASKS设置为1_000_000并在工厂生成器中.virtual() ,则该程序将失败,并显示内存不足错误。 一百万个OS级线程占用大量内存。 但是使用虚拟线程,它可以工作。

至少,它应该可以工作,并且对我之前的Loom版本确实有效。 不幸的是,在12月5日下载的构建中,我得到了一个核心转储。 当我尝试使用Loom时,这时有发生。 希望它会在您尝试时解决。

现在,您可以尝试更复杂的事情了。 亨氏·卡布兹(Heinz Kabutz)最近为益智游戏提供了一个程序,该程序可加载数千个Dilbert卡通图像。 对于每个日历日,都有一个页面,例如https://dilbert.com/strip/2011-06-05 。 程序读取这些页面,在每个页面中找到卡通图像的URL,然后加载每个图像。 这是一堆乱七八糟的期货 ,有点像:

CompletableFuture.completedFuture(getUrlForDate(date)).thenComposeAsync(this::readPage, executor).thenApply(this::getImageUrl).thenComposeAsync(this::readPage).thenAccept(this::process);

使用光纤,代码更加清晰:

exec.submit(() -> {      String page = new String(readPage(getUrlForDate(date)));byte[] image = readPage(getImageUrl(page));process(image);
});

当然,每个对readPage的调用readPage块,但是对于纤维,我们不在乎。

尝试一下您关心的事情。 阅读大量网页,进行处理,进行更多的阻塞读取,并享受光纤阻塞便宜的事实。

结构化的一致性

Project Loom的最初动机是实现光纤,但今年早些时候,该项目开始了针对结构化并发的实验性API。 在这篇强烈推荐的文章 (从中拍摄以下图像)中,Nathaniel Smith提出了结构化的并发形式。 这是他的中心论点。 在新线程中启动任务实际上并不比使用GOTO编程好,即有害:

new Thread(runnable).start();

当多个线程在没有协调的情况下运行时,这将是意大利面条代码。 在1960年代,结构化编程将goto替换为分支,循环和函数:

现在,结构化并发的时机已经到来。 启动并发任务时,通过阅读程序文本,我们应该知道它们何时全部完成。

这样,我们可以控制任务使用的资源。

到2019年夏季,Project Loom有了一个用于表达结构化并发的API。 不幸的是,由于最近进行了统一线程和光纤API的实验,该API目前处于混乱状态,但是您可以通过http://jdk.java.net/loom/上的原型进行尝试。

在这里,我们安排了许多任务:

FiberScope scope = FiberScope.open();
for (int i = 0; i < NTASKS; i++) {scope.schedule(() -> run(i));
}
scope.close();

调用scope.close()阻塞,直到所有光纤完成。 请记住,光纤阻塞不是问题。 一旦关闭示波器,您就可以确定光纤已经完成。

FiberScope是可FiberScope的,因此您可以使用try -with-resources语句:

try (var scope = FiberScope.open()) {...
}

但是,如果其中一项任务永远无法完成怎么办?

您可以使用截止日期( Instant )或超时( Duration )创建范围:

try (var scope = FiberScope.open(Instant.now().plusSeconds(30))) {for (...)scope.schedule(...);
}

截止期限/超时之前尚未完成的所有光纤都将被取消。 怎么样? 继续阅读。

消除

取消一直是Java的痛苦。 按照惯例,您可以通过中断线程来取消线程。 如果线程正在阻塞,则阻塞操作以InterruptedException终止。 否则,设置中断状态标志。 正确地进行检查是乏味的。 可以重置中断状态,或者InterruptedException是已检查的异常,这没有帮助。

java.util.concurrent中取消的处理一直不一致。 考虑ExecutorService.invokeAny 。 如果有任务产生结果,则其他任务将被取消。 但是CompletableFuture.anyOf允许所有任务运行完成,即使其结果将被忽略。

2019年夏季的Project Loom API解决了取消问题。 在该版本中,光纤具有cancel操作,类似于interrupt ,但是取消是不可撤销的。 如果当前光纤已被取消,则静态Fiber.cancelled方法将返回true

当示波器超时时,其光纤将被取消。

取消可以由FiberScope构造函数中的以下选项控制。

  • CANCEL_AT_CLOSE :关闭范围取消所有计划的光纤而不是阻塞
  • PROPAGATE_CANCEL :如果取消拥有光纤,则任何新调度的光纤都会自动取消
  • IGNORE_CANCEL :无法取消预定的光纤

所有这些选项都未在顶层设置。 PROPAGATE_CANCELIGNORE_CANCEL选项是从父范围继承的。

如您所见,有相当多的可调整性。 我们必须看看重新考虑此问题后会发生什么。 对于结构化并发,当示波器超时或被强制关闭时,必须自动取消示波器中的所有光纤。

螺纹局部

让我感到惊讶的是,Project Loom实现者的痛苦之一是ThreadLocal变量,以及更深奥的东西-上下文类加载器AccessControlContext 。 我不知道有那么多东西骑在线程上。

如果您的数据结构不适合并发访问,则有时可以在每个线程中使用一个实例。 经典示例是SimpleDateFormat 。 当然,您可以继续构造新的格式化程序对象,但这并不高效。 所以你想分享一个。 但是全球

public static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

将无法正常工作。 如果两个线程同时访问它,则格式可能会混乱。

因此,每个线程中有一个是有意义的:

public static final ThreadLocal<SimpleDateFormat> dateFormat= ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));

要访问实际的格式化程序,请致电

String dateStamp = dateFormat.get().format(new Date());

首次调用get时,将调用构造函数中的lambda。 从那时起,get方法返回属于当前线程的实例。

对于线程,这是公认的做法。 但是,如果真的有一百万个光纤,您是否真的想拥有一百万个实例?

这对我来说不是问题,因为使用线程安全的东西(如java.time格式化程序)似乎更容易。 但是Project Loom一直在考虑“范围本地”对象-那些FiberScope被重新激活了。

在线程与处理器数量一样多的情况下,线程局部变量也已被用作处理器局部性的近似值。 可以实际模拟用户意图的API可以支持此功能。

项目状况

想要使用Project Loom的开发人员自然会沉迷于API,如您所见,该API尚未解决。 但是,许多实施工作都处于幕后。

一个关键部分是在操作阻塞时使光纤停放。 已经完成了网络连接,因此您可以在光纤内连接到网站,数据库等。 当前不支持本地文件操作块时的停车。

实际上,在JDK 11、12和13中已经重新实现了这些库,这是对频繁发布实用程序的致敬。

目前尚不支持在监视器上进行阻塞( synchronized块和方法),但最终需要这样做。 ReentrantLock现在可以了。

如果光纤以本机方法阻塞,则将“固定”线程,并且所有光纤都不会前进。 Project Loom对此无能为力。

Method.invoke需要更多工作才能得到支持。

有关调试和监视支持的工作正在进行中。

如前所述,稳定性仍然是一个问题。

最重要的是,性能还有一段路要走。 停放光纤不是免费的午餐。 每次都需要替换运行时堆栈的一部分。

在所有这些方面都取得了很大的进展,所以让我们回顾一下开发人员关心的API。 现在是查看Project Loom并考虑如何使用它的好时机。

同一类代表线和纤维对您有价值吗? 还是您希望将某些Thread行李丢掉? 您是否认同结构化并发的承诺?

试一下Project Loom,看看它如何与您的应用程序和框架一起工作,并为无畏的开发团队提供反馈!

翻译自: https://www.javacodegeeks.com/2019/12/project-loom.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/340856.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java mybatis 教程_(整理)MyBatis入门教程(一)

本文转载&#xff1a;本人文笔不行&#xff0c;根据上面博客内容引导&#xff0c;自己整理了一些东西首先给大家推荐几个网页&#xff1a;MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code&#xff0c;并且改名为MyBa…

2020版北大中文核心期刊目录_收藏备用最新版:《中文核心期刊要目总览》北大中文核心期刊目录...

《中文核心期刊要目总览》是学术界对某类期刊的定义&#xff0c;一种期刊等级的划分。它的对象是&#xff0c;中文学术期刊&#xff0c;是根据期刊影响因子等诸多因素所划分的期刊。中文核心期刊是北京大学图书馆联合众多学术界权威专家鉴定&#xff0c;目前受到了学术界的广泛…

java中多个输入框搜索_如何在一个搜索框中输入多个字段的值进行查询?

搜索export default {data() {return {input: ,//用来接受input框的值name:,// 用来存储foreach的对应的值id:,// 用来存储foreach的对应的值dq:// 用来存储foreach的对应的值}},methods:{submit(){console.log(this.input);// 打印let str this.input;// 声明变量接受input的…

fedora如何隐藏顶部状态栏_藏在 iOS 13 里的 9 个隐藏小技巧

正文共&#xff1a;1797字 10图1.从控制中心直接选择无线网络和蓝牙配件苹果首次在 iOS 7 中加入了控制中心&#xff0c;允许用户进行一些快速操作&#xff0c;例如打开/关闭飞行模式、打开/关闭蜂窝网络、打开/关闭 Wi-Fi 等。但很多控制都只停留在一级菜单&#xff0c;你只能…

java的封装性的优点_18、Java的三大特性之封装

Java的三大特性java是一个面向对象的语言&#xff0c;所以java也有面向对象语言的三大特性&#xff1a;继承&#xff0c;封装&#xff0c;多态&#xff0c;任何一个java项目&#xff0c;都会用到这三种特性&#xff0c;所以掌握好这三大特性非常的重要。封装我们为什么要使用封…

groovy 字符串截取最后一个_Java基础篇——字符串详解

字符串的声明字符串是内存中连续排列的0个或多个字符。不变字符串是指字符串一旦创建&#xff0c;其内容就不能改变&#xff0c;Java中使用String类来处理不变字符串&#xff0c;在对String类的实例进行查找、比较、拼接等操作时&#xff0c;既不能输入新字符&#xff0c;又不能…

java中链式调用_Java及Android中常用链式调用写法简单示例

本文实例讲述了Java及Android中常用链式调用写法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;最近发现&#xff0c;目前大火的许多开源框架中&#xff0c;大多都使用了一种"(方法).(方法).(方法)"的形式进行调用&#xff0c;最典型的就是RxJava。android…

C什么k什么_K线图基础知识丨什么是K线散兵坑形态?K线散兵坑形态的操作与案例详解...

本文总共999字&#xff0c;预计阅读需要3分钟今天我们给大家带来的是K线散兵坑形态&#xff0c;那么K线散兵坑形态应该怎么来操作呢&#xff1f;今天我们就结合相应的实战案例来为大家讲解一下吧。K线散兵坑形态的简介散兵坑是指在股价缓慢上涨过程中.成交量也逐渐放大&#xf…

support v4官方下载_掌心长兴客户端下载-掌心长兴ap下载v4.1.4 安卓官方版

掌心长兴app是一款为广大用户开发的新闻资讯软件。在这里用户可以清晰的了解今日热点新闻&#xff0c;最新新闻直播电台应有尽有&#xff01;让你全方面了解周边新鲜事&#xff01;还有各种常用功能的代办查询服务。有需要的用户&#xff0c;欢迎现在下载体验哦掌心长兴客户端介…

javafx 调用java_Java验证(javafx)

javafx 调用java验证是核心javafx框架所缺少的一件事。 为了弥补这一空白&#xff0c; controlsfx中已经存在一个第三方验证库 。 但是&#xff0c;我有一个问题&#xff1a;它不是在考虑FXML的情况下创建的。 这并不是说它不是一个很好的库&#xff0c;只是错过了这个细节&…

win10分辨率不能调整_Win10系统分辨率不能修改怎么办?屏幕分辨率的调节方法...

Win10系统电脑屏幕分辨率无法调节怎么办&#xff1f;电脑屏幕分辨率不能修改怎么办&#xff1f;近日有很多用户询问电脑显示器分辨率不能修改的问题&#xff0c;下面就给大家分享解决方法。解决方法&#xff1a;1、在win10系统桌面空白处单击鼠标右键&#xff0c;在弹出的菜单中…

笔记本电脑电源已接通未充电_dell xps15 电源已接通 未充电 维修方法

&#xff08;去年写的文章&#xff0c;在知乎也存一份&#xff09;网上类似的文章很多&#xff0c;这里总结一下&#xff0c;这个问题按照严重程度可以分为四个层次&#xff1a;电源计划问题&#xff0c;大部分百度出来说的都是这个&#xff0c;实际上这个问题 等于没有问题。改…

mysql bc_正则表达式——MySQL搜索过滤

正则表达式介绍在数据库的数据过滤过程中只用WHERE子句和LIKE操作符都是对于已知值进行的不管是匹配一个还是多个值&#xff0c;测试大于还是小于已知值&#xff0c;或者检查某个范围的值&#xff0c;都是使用已知的值当然MySQL语句也提供了通配符百分号(%)和下划线(_)来匹配多…

everything安装版和便携版有什么区别_A2奶粉内幕:国行版和澳洲版有什么区别 贵的不一定好!...

点击上方蓝字 关注我们申明&#xff1a;此文章来自第三方平台&#xff0c;绝无倾向性诱导。二桐粑粑转载分享。A2是全球首款添加了“A2-β酪蛋白”的奶粉&#xff0c;由新西兰A2公司于2013年推出&#xff0c;这款奶粉在澳洲一上架&#xff0c;就被妈妈们一扫而空。之后A2公司针…

java 什么时候用递归_如果要用Java实现算法,一定慎用递归

现象 &#xff1a;递归是我们很经典的一种算法实现&#xff0c;可以很好的描述一个算法的原理&#xff01;对于算法的描述、表现和代码结构理解上&#xff0c;递归都是不错的选择&#xff01;但是本文想说的是java实现一个递归算法的时候尽量不要用递归实现&#xff0c;而是转换…

excel分两个独立窗口_Excel2010 多个独立窗口,解决单窗口无法显示多个文件的问题...

当我们需要编辑多个excel的时候&#xff0c;就会发现一个问题&#xff0c;Excel不能一个窗口下显示多个文档&#xff0c;每次编辑都进行切换就太麻烦了&#xff0c;那如何能解决这个问题呢&#xff1f;接下来跟我一起看看吧&#xff01;首先在开始菜单输入regedit.exe命令&…

excel冻结窗口_excel怎么冻结窗口?excel冻结窗口怎么设置?

excel冻结行或列的技巧教程&#xff1a;一、冻结第一列1.选择 视图 > 冻结窗格 > 冻结第一列。2.列A和列B之间出现的细线表明第一列已冻结。二、冻结前两列1.选择第三列。2.选择 查看 > 冻结窗格 > 冻结窗格。三、冻结列和行1.选择要在滚动时保持可见的行下方和列右…

web service接口_win7 添加环回网卡+H3C 模拟器 防火墙开启Web功能

1、按下win R键&#xff0c;在其中输入&#xff1a;hdwwiz&#xff0c;然后点击“确定”或者按回车键&#xff0c;打开“添加硬件”对话框。2、看到如下界面时&#xff0c;选择“网络适配器”(如下图所示)&#xff0c; 在接着出现的界面中&#xff0c;左方“厂商”一栏里选择“…

java 实现nfa的化简_DFA与NFA的等价性,DFA化简

等价性对于每个NFA M存在一个DFA M’&#xff0c;使得L(M)L(M’)--------等价性证明&#xff0c;NFA的确定化假定NFA M&#xff0c;我们对M的状态转换图进行以下改造&#xff1a;解决初始状态唯一性&#xff1a;引进新的初态结点X和终态结点Y&#xff0c;X,Y∉S&#xff0c;从X…

eclipse查看git地址_gitamp;github的入门实战

一、Git概述&#xff08;1&#xff09;定义Git是目前世界上最先进的分布式版本控制系统。&#xff08;2&#xff09;能干什么&#xff1f;解决冲突、管理权限、代码备份、协同开发、版本还原、历史追查、版本记录、分支管理、代码审查&#xff08;3&#xff09;集中管理型版本管…