java 多线程和并行编程_Java 8中的并行和异步编程

java 多线程和并行编程

并行代码是在多个线程上运行的代码,曾经是许多经验丰富的开发人员的噩梦,但是Java 8带来了许多更改,这些更改应该使这种提高性能的窍门更加易于管理。

并行流

在Java 8之前,并行(或并发)代码与顺序代码之间存在很大差异。 调试非顺序代码也非常困难。 像通常那样简单地设置一个断点并按照流程进行操作,将删除并行方面,如果这是导致该错误的原因,那么这是一个问题。

幸运的是,Java 8为我们提供了流,这是自Bean以来对Java开发人员而言最大的事情。 如果您不知道它们是什么,则Stream API可以处理功能问题中的元素序列。 (在这里检查流与.NET的LINQ之间的比较。)流的优点之一是代码的结构保持不变:无论是顺序的还是并发的,它都保持可读性。

为了使您的代码并行运行,只需使用.parallelStream()而不是.stream() (或者,如果您不是流的创建者,则可以使用stream .parallel() )。

但是,仅仅因为它很容易,并不意味着并行代码始终是最佳选择。 您应该始终考虑在代码段中使用并发是否有意义。 该决定中最重要的因素将是速度:仅当并发使您的代码比其顺序对应的代码快时才使用并发。

速度问题

并行代码通过使用多个线程而不是顺序代码使用的单个线程而获得了速度优势。 确定创建多少个线程可能是一个棘手的问题,因为更多的线程并不总是会导致更快的代码:如果使用太多的线程,则代码的性能实际上可能会下降。

有几条规则可以告诉您选择多少线程。 这主要取决于您要执行的操作类型以及可用内核的数量。

计算密集型操作应使用少于或等于内核数的线程数量,而IO密集型操作(如复制文件)对CPU无效,因此可以使用更多线程。 该代码不知道哪种情况适用,除非您告诉它该怎么做。 否则,它将默认为线程数等于内核数。

在两种主要情况下,并行运行代码而不是顺序运行代码很有用:耗时的任务和在大集合上运行的任务。 Java 8带来了一种处理大集合的新方法,即使用流。 流具有惰性的内置效率:它们使用惰性评估,通过做不必要的事情来节省资源。 这与并行性不同,只要它运行得更快,它就不会在乎资源。 因此,对于大型集合,您可能不需要经典的并行性。

================================================== ====================

异步

JavaScript的教训

Java开发人员很少会说他们从看过JavaScript中学到了什么,但是在异步编程方面,JavaScript实际上是正确的。 作为一种从根本上异步的语言,JavaScript在实施不好时会带来多大痛苦。 它从回调开始,后来被Promise取代。 许诺的一个重要好处是它有两个“通道”:一个用于数据,另一个用于错误。 JavaScript承诺可能看起来像这样:

func
.then(f1)
.catch(e1)
.then(f2)
.catch(e2);

因此,当原始函数获得成功结果时,将调用f1,但是如果引发错误,则将调用e1。 这可能会使它返回成功轨道(f2),或导致另一个错误(e2)。 您可以从数据跟踪到错误跟踪再返回。

JavaScript承诺的Java版本称为CompletableFuture 。

未来发展

CompletableFuture同时实现FutureCompletionStage接口。 Java8之前就已经存在Future ,但是它本身对开发人员并不十分友好。 您只能使用.get()方法来获取异步计算的结果,该方法会阻塞其余部分(使异步部分大部分时间变得毫无意义),并且您需要手动实现每种情况。 添加CompletionStage接口是使Java异步编程可行的突破。

CompletionStage是一个承诺,即最终将完成计算的承诺。 它包含许多方法,可让您附加将在完成时执行的回调。 现在我们可以处理结果而不会阻塞。

有两种主要方法可让您启动代码的异步部分: supplyAsync如果您想对方法的结果进行某些操作)和runAsync如果您不想这样做)。

CompletableFuture.runAsync(() → System.out.println("Run async in completable future " + Thread.currentThread()));
CompletableFuture.supplyAsync(() → 5);

回呼

现在,您可以添加这些回调以处理supplyAsync的结果

CompletableFuture.supplyAsync(() → 5)
.thenApply(i → i * 3)
.thenAccept(i → System.out.println(“The result is “ + i)
.thenRun(() → System.out.println("Finished."));

.thenApply.thenApply.map函数类似:它执行转换。 在上面的示例中,它将结果(5)乘以3。然后将结果(15)进一步传递给管道。

.thenAccept对结果执行一种方法,而无需对其进行转换。 它也不会返回结果。 它将在控制台上显示“结果为15”。 可以将它与.foreach方法进行流比较。

.thenRun不使用异步操作的结果,也不返回任何内容,它只是等待调用其Runnable直到上一步完成为止。

异步处理

上面所有的回调方法也都具有异步版本: thenRunAsyncthenApplyAsync等。这些版本可以在自己的线程上运行,它们为您提供了额外的控制权,因为您可以告诉它使用哪个ForkJoinPool

如果不使用异步版本,则所有回调将在同一线程上执行。

当事情出错时

当出现问题时,将使用exceptionally方法来处理异常。 您可以给它提供一个方法,该方法返回一个值以返回数据轨道,或引发(新)异常。

…
.exceptionally(ex → new Foo())
.thenAccept(this::bar);

合并与撰写

您可以使用thenCompose方法链接多个CompletableFutures 。 没有它,结果将嵌套CompletableFutures 。 这使得thenComposethenApplyflatMapmap用于流。

CompletableFuture.supplyAsync(() -> "Hello")
.thenCompose(s -> CompletableFuture
.supplyAsync(() -> s + "World"));

如果要合并两个CompletableFutures的结果,则需要一个方便地称为thenCombine的方法。

future.thenCombine(future2, Integer::sum)
.thenAccept(value →  System.out.println(value));

如您在上面的示例中看到的那样,可以使用所有喜欢的CompletionStage方法像普通的CompletableFuture一样处理thenCombine中的回调结果。

结论

在寻求更快的代码时,并行编程不再是不可克服的障碍。 Java 8使该过程尽可能简单明了,因此,可能从中受益的任何代码都可以在所有线程上被拉,踢和尖叫,进入多核未来,实际上,这只是现在天。 我的意思是:这很容易做到,因此请尝试一下,看看自己的优势。

翻译自: https://www.javacodegeeks.com/2018/04/parallel-and-asynchronous-programming-in-java-8.html

java 多线程和并行编程

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

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

相关文章

java bi报表工具_7款顶级开源BI(商务智能)软件和报表工具

在这个信息化时代,每分每秒都产生海量数据。在海量数据中,挖掘出有用的数据,并且能以较人性化、直观的方式展示这些数据,变得尤为重要。本文将介绍 7款顶级开源 BI(商务智能)软件和报表工具,用于商业数据的分析处理&am…

Linux命令之 DNF -- 新一代的 RPM 软件包管理器

文章目录一、命令介绍二、安装 DNF三、DNF 命令(一)主要命令1. 安装、升级和删除软件包2. 查询和检查软件包3. 执行其它功能(二)插件命令四、选项参数五、命令示例(一)安装、升级和删除软件包安装软件包安装…

抽取大小: 高斯sigma_无服务器:SLAppForge Sigma入门

抽取大小: 高斯sigma! Cmere。 寻找某事? 无服务器,是吗? 在上面。 进入海峡,在“ Sigma”标志处右转。 (嗯,还不要怪我们;至少我们认为这很容易!) 我们…

java多线程 修改优先级_Java多线程-线程的调度(优先级)

与线程休眠类似,线程的优先级仍然无法保障线程的执行次序。只不过,优先级高的线程获取CPU资源的概率较大,优先级低的并非没机会执行。线程的优先级用1-10之间的整数表示,数值越大优先级越高,默认的优先级为5。在一个线…

Linux 命令之 apt-mark -- 对 APT 软件包设置标记

文章目录一、命令介绍二、常用命令三、命令示例(一)将软件包标记为 unhold一、命令介绍 apt-mark 可以对软件包设置标记,列出或过滤拥有某个标记的软件包。 二、常用命令 命令说明auto标记指定软件包为自动安装manual标记指定软件包为手动…

java魔兽猎人_Java基于Swing实现的打猎射击游戏代码

package Game;import static java.lang.Math.random;import java.awt.*;import java.awt.event.*;import javax.swing.*;public class MainFrame extends JFrame {private static final long serialVersionUID 1L;private static long score 0;// 分数private static Integer…

Linux 命令之 aptitude -- APT 软件包管理工具

文章目录一、命令介绍二、常用选项三、命令示例(一)安装、升级和删除软件包升级系统所有的软件包将系统升级到新的发行版安全升级系统的软件包安装软件包删除软件包(保留有关的配置文件)彻底删除软件包(删除有关的配置…

微软 azure_在Microsoft Azure上运行Eclipse MicroProfile

微软 azure在本文中,我将通过展示如何在Microsoft Azure Web Apps for Containers中执行操作来跟踪有关在Oracle Cloud中运行Eclipse MicroProfile应用程序的系列文章。 我正在使用与以前的帖子相同的简单应用程序CloudEE Duke 。 唯一的区别是,我现在将…

java文件复制速度_【Java】Java代码拷贝文件的速度

Java代码拷贝文件的速度究竟有多快?前言最近学习Java到了流处理,其中有种流叫FileInputStream和FileOutputStream,简单来说,就是操作文件的,老师给我们示范了一个非常有趣的例子,用代码拷贝文件&#xff01…

vim 的配置详解/键盘映射配置详解

文章目录特性设置配置快捷键(键映射配置)键盘符号键盘映射命令和不同模式的对应关系取消键盘映射查看键盘映射在目录 /etc/ 下面,有个名为 vimrc 的文件,这是系统中公共的 vim 配置文件,对所有用户都有效。而在每个…

开闭原则 依赖倒置原则_坚实原则:依赖倒置原则

开闭原则 依赖倒置原则到目前为止,我们只研究了单一职责 , 打开/关闭 , liskov替换和接口隔离原则。 依赖倒置是我们所要研究的最后一个原理之一。 该原则指出 答:高级模块不应依赖于低级模块。 两者都应依赖抽象。 B.抽象不应…

java的传值调用什么_Java的传值调用

(本文非引战或diss,只是说出自己的理解,欢迎摆正心态观看或探讨)引子之所以写这篇文章是因为前些天写了一篇《Java中真的只有值传递么?》探讨了网上关于Java只有值传递的说法,当时写这篇文章的缘由是因为之前看的文章讲解的Java只…

Linux 命令之 apt -- Debian Linux 新一代的软件包管理工具

文章目录 一、命令介绍二、常用命令三、常用选项四、命令示例(一)安装、更新和删除软件包安装指定的软件包安装软件包的同时修复依赖问题安装指定版本的软件包安装本地的 deb 包文件删除软件包,保留配置文件删除软件包,不保留配置文件将已经安装的但是不再使用的软件包删除…

liskov替换原则_坚实原则:Liskov替代原则

liskov替换原则以前,我们深入研究了坚实的原则,包括单一责任和开放/封闭原则。 Liskov替代原则(LSP)是子类型关系的一种特殊定义,称为(强)行为子类型, 假设对象S是对象T的子类型&a…

java 聚合_Java聚合

聚合如果一个类有一个类的实体引用(类中的类),则它称为聚合。 聚合表示HAS-A关系。考虑有一种情况,Employee对象包含许多信息,例如:id,name,emailId等。它包含另一个类对象:address,…

Linux 命令之 dpkg --Debian 的一个底层包管理工具

文章目录 一、命令介绍二、deb 软件包命名规则三、软件包管理相关文件/目录四、dpkg 数据库五、子命令六、常用选项(一)安装、升级和删除软件包(二)查询和检验软件包(三)其它七、命令示例(一)安装、升级和卸载软件包安装指定的软件包解开软件包到系统目录但不配置配置软…

java jep_Java 10 – JEP 286:局部变量类型推断

java jepJava 10即将发布,RC Build可在此处获得 。 可在此处找到此发行版的目标功能。 在针对Java 10的所有JEP中,开发人员社区中最有趣且最受关注的是286:Local-Variable Type Inference 。 什么是局部变量类型推断? 我们在Java…

java ffmpeg 视频水印_java 实现视频转换通用工具类:视频加水印-Ffmpeg(五-1)

java 实现视频转换通用工具类:视频相互转换-Ffmpeg(三)说明:视频加水印支持右上角、左上角、左下角、右下角、底部居中几个方位1.根据水印文字---添加视频水印/*** 根据水印文字---添加视频水印* param srcPath 原视频路径* param tarVideoPath 生成后的…

手动 clone 安装 Homebrew

文章目录 手动 clone 安装 HomebrewHomebrew 换源替换 homebrew 源替换 homebrew-core 源替换 homebrew-bottles 源bash用户zsh 用户更新 Homebrew手动 clone 安装 Homebrew 首先进入 homebrew 目录:cd "$(brew --repo)/Library/Taps/homebrew/"创建目录 homebrew-c…

lambda 匿名内部类_Lambda运行时内部:窥视无服务器巢穴

lambda 匿名内部类有没有想过lambda里面是什么样的? 不要怀疑了 让我们找出答案。 自从2014年问世以来,AWS的lambda函数就成为一个热门话题,在无服务器计算领域开辟了全新的历史。 无状态,零维护,按次执行的好东西实际…