并行代码是在多个线程上运行的代码,曾经是许多经验丰富的开发人员的噩梦,但是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 8中的并行和异步编程相关推荐

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

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

  2. 阿里技术专家加多:Java异步编程实战之基于JDK中的Future实现异步编程 | 文末赠书...

    正文共:14244 字 8 图 预计阅读时间: 36 分钟 本节内容摘自<Java异步编程实战>中的一小节. 一.前言 本节主要讲解如何使用JDK中的Future实现异步编程,这包含如何使 ...

  3. 阿里技术专家加多:Java异步编程实战之基于JDK中的Future实现异步编程

    正文共:14244 字 8 图 预计阅读时间: 36 分钟 本节内容摘自<Java异步编程实战>中的一小节. 一.前言 本节主要讲解如何使用JDK中的Future实现异步编程,这包含如何使 ...

  4. java futuretask 源码解析_Java异步编程——深入源码分析FutureTask

    Java的异步编程是一项非常常用的多线程技术. 之前通过源码详细分析了ThreadPoolExecutor<你真的懂ThreadPoolExecutor线程池技术吗?看了源码你会有全新的认识&g ...

  5. 在 C++ 中使用 PPL 进行异步编程

    莱坞星探通常要拒绝那些有抱负的演员时,都会轻蔑地说:"别联系我们,我们会联系你的."然而对于开发人员来说,那句话却道出了许多软件框架工作的秘密,与其让程序员驱动整个应用程序的控制流 ...

  6. java coroutine类_Coroutines和Rxjava异步编程对比

    这一系列的文章将会用来进行Coroutines和Rxjava在解决异步编程方面的对比. 案例一:为一个快速启动的App创建复杂的对象 如果希望自己的应用程序能够快速启动,那么处理创建对象的过程非常重要 ...

  7. day01--java基础编程:计算机基础知识 ,java语言概述,java开发环境搭建,eclipse概述,创建简单java项目,JDK JRE JVM的关系,java开发中的命名规范,编程风格

    1 Day01–Java开发环境+HelloWorld 1.1 计算机基础知识 资料下载网址:刘沛霞 18600949004 code.tarena.com.cn tarenacode code_20 ...

  8. 解释java程序中的异常机制_Java编程中的异常机制

    本文旨在以初学者的角度来学习Java异常的知识,尽量简单,一些细枝末节的知识不会讲述,但不影响对知识的掌握. (比如try-catch可以嵌套,不太会这么用) 1.什么是异常 我们先举个例子 int ...

  9. Java 异步编程 (5 种异步实现方式详解)

    同步操作如果遇到一个耗时的方法,需要阻塞等待,那么我们有没有办法解决呢?让它异步执行,下面我会详解异步及实现 @mikechen 目录 什么是异步? 一.线程异步 二.Future异步 三.Compl ...

最新文章

  1. mysql 中文字段名_10个MySQL的数据库技巧~
  2. Linux shell:shell 命令的返回值和输出
  3. java04376_Java - jdbc mybatis
  4. 如何把word分装到两个byte_如何核对两个Word文档的内容差别?同事加班半小时,我只花了30秒...
  5. python博客项目评论_Python 爬虫入门——小项目实战(自动私信博客园某篇博客下的评论人,随机发送一条笑话,完整代码在博文最后)...
  6. python基础-字典的增删改查
  7. eclipse 安装图形插件(图形化编程)
  8. 强烈建议大家把 CBCentralManager.h 里面的代理方法全部看一遍(就是翻译一遍,别偷懒)。@file CBCentralManager.h...
  9. CISCO 路由器(1)
  10. 中国的 GitHub 要来了?
  11. iOS 之NSOperation(一)
  12. php包含大马执行,对于某个PHP大马的分析
  13. Bootstrap小图标
  14. c语言int doubt,c语言错误error: incompatible types in assignment
  15. java通过LocalDateTime获取上周几
  16. ROS——Gazebo仿真——全向轮小车——运动学模型分析
  17. 【2月每日一题】leetcode Java + c++版 (6 完结)
  18. 自己的网页嵌入外部邮箱登陆
  19. 电脑桌面的word文件丢失了怎么找回?7个解决方法!
  20. X86:2:X86处理器架构

热门文章

  1. Spark SQL(十)之基于物品的推荐公式
  2. JavaFX仿windows文件管理器目录树
  3. Redis 5.0 正式版发布了,19 个新特性
  4. Class的 getSuperclass与getGenericSuperclass区别
  5. java基础的知识点(一)
  6. SpringMVC的上传与下载
  7. python3 爬虫例子_如何让你写的爬虫速度像坐火箭一样快【并发请求】
  8. 生物信息 python 书籍_用python做生物信息数据分析(1-环境准备)
  9. kafka生产者开发方式
  10. MySQL的source命令不加分号和delimiter的使用