java jsr_分叉并加入Java 7 – JSR 166并发实用程序

java jsr

Java 7最有趣的改进之一是对并发的更好支持。 借助JSR 166并发实用程序,我们获得了一些非常有用的并发改进。 在我看来,fork-join库在软件工程中具有很高的实际应用潜力。 Fork and join为算法提供了非常简单的编程模型,可以将其实现为递归任务。 有很多算法可以使用分治法来实现。

在未来几年中,我们将看到标准台式机,笔记本电脑和服务器计算机中的内核数量将不断增加。 原因很简单:添加额外的内核要比构建更快的单个处理器便宜。 因此,我们将不得不编写更多支持并发的软件以利用更好的硬件。

老实说,我不喜欢并发。 我的个人规则是“您需要一个充分的理由来实现并发,并且如果需要做的话必须非常小心。”在过去的几年中,我看到的错误实现多于工作。 这就是为什么我喜欢fork&join库的原因。 清晰的编程模型可实现样板代码,可防止您出错。 但是,如果您打算使用fork和join,请花一些时间来了解其行为。

文件#1和#2中的示例与Java 7文档中的示例代码非常相似。 通常,使用递归算法的斐波那契数不是一个好主意,因为存在更好的线性解决方案(请比较http://nayuki.eigenstate.org/page/fast-fibonacci-algorithms ),但它更易于实现和理解相对于其它的。 因此,让我们看一下示例:

// File #1: FibonacciTask.java  [error handling, parameter validation and asserts removed] package com.sprunck.sample;import java.util.concurrent.RecursiveTask;public class FibonacciTask extends RecursiveTask<Long> {private static final long serialVersionUID = 1L;private final long inputValue;public FibonacciTask(long inputValue) {this.inputValue = inputValue;}@Overridepublic Long compute() {if (inputValue == 0L) {return 0L;} else if (inputValue <= 2L) {return 1L;} else {final FibonacciTask firstWorker = new FibonacciTask(inputValue - 1L);firstWorker.fork();final FibonacciTask secondWorker = new FibonacciTask(inputValue - 2L);return secondWorker.compute() + firstWorker.join();}}
}
// File #2: FibonacciTaskTest.java package com.sprunck.sample;import java.util.concurrent.ForkJoinPool;
import junit.framework.Assert;
import org.junit.Test;public class FibonacciTaskTest {// it makes no sense to create more threads than available cores (no speed improvement here)private static final int AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors();// create thread poolprivate final ForkJoinPool pool = new ForkJoinPool(AVAILABLE_PROCESSORS);@Testpublic void testFibonacciArray() {// more test data: http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibtable.htmllong results[] = { 0L, 1L, 1L, 2L, 3L, 5L, 8L, 13L, 21L, 34L, 55L, 89L, 144L, 233L, 377L, 610L, 987L, 1597L,2584L, 4181L, 6765L };for (int inputValue = 0; inputValue < results.length; inputValue++) {final FibonacciTask task = new FibonacciTask(inputValue);System.out.print("Fibonacci(" + inputValue + ") = ");final long result = pool.invoke(task);System.out.println(result);Assert.assertEquals(results[inputValue], result);}}
}

// FibonacciTaskTest.java的输出

Fibonacci(0) = 0
Fibonacci(1) = 1
Fibonacci(2) = 1
Fibonacci(3) = 2
Fibonacci(4) = 3
Fibonacci(5) = 5
Fibonacci(6) = 8
Fibonacci(7) = 13
Fibonacci(8) = 21
Fibonacci(9) = 34
Fibonacci(10) = 55
Fibonacci(11) = 89
Fibonacci(12) = 144
Fibonacci(13) = 233
Fibonacci(14) = 377
Fibonacci(15) = 610
Fibonacci(16) = 987
Fibonacci(17) = 1597
Fibonacci(18) = 2584
Fibonacci(19) = 4181
Fibonacci(20) = 6765

到目前为止,这是一个简单明了的解决方案。 没有用于并行的样板代码,例如线程同步。

但我想鼓励您更深入地了解解决方案中发生的情况。 在文件#3和#4中,您可以找到同一程序的增强版本。 第一个版本和第二个版本之间的唯一区别是,一些代码可以跟踪执行过程中发生的事情,而较小的slowTask()可以模拟更实际的行为。

// File #3: FibonacciTaskTraces.java package com.sprunck.sample;import java.util.concurrent.RecursiveTask;public class FibonacciTaskTraces extends RecursiveTask<Long> {private static final long serialVersionUID = 1L;// just needed to format debug outputpublic static final String OUTPUT_PREFIX = " | ";private final String prefix;private final long inputValue;public FibonacciTaskTraces(long inputValue, final String prefix) {this.inputValue = inputValue;this.prefix = prefix;}@Overridepublic Long compute() {if (inputValue == 0L) {slowTask();return 0L;} else if (inputValue <= 2L) {slowTask();return 1L;} else {final long firstValue = inputValue - 1L;System.out.println(prefix + " - Fibonacci(" + firstValue + ") <- " + Thread.currentThread().getName()+ " (fork) ");final FibonacciTaskTraces firstWorker = new FibonacciTaskTraces(firstValue, prefix + OUTPUT_PREFIX);firstWorker.fork();final long secondValue = inputValue - 2L;System.out.println(prefix + " - Fibonacci(" + secondValue + ") <- " + Thread.currentThread().getName());final FibonacciTaskTraces secondWorker = new FibonacciTaskTraces(secondValue, prefix + OUTPUT_PREFIX);long result = secondWorker.compute() + firstWorker.join();System.out.println(prefix + " - Fibonacci(" + inputValue + ") = " + result + " <- "+ Thread.currentThread().getName() + " (join)");slowTask();return result;}}/** just simulate a longer running task (with out disturbing the other threads) */private void slowTask() {for (int k = 0, i = 0; i < 1000 * 1000 * 100; i++) {i = i + k;}}
}
// File #4: FibonacciTaskTracesTask.javapackage com.sprunck.sample;import java.util.concurrent.ForkJoinPool;
import junit.framework.Assert;
import org.junit.Test;public class  FibonacciTaskTracesTest {// it makes no sense to create more threads than available cores (no speed improvement here)private static final int AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors();// create thread poolprivate final ForkJoinPool pool = new ForkJoinPool(AVAILABLE_PROCESSORS);@Testpublic void testFibonacciArrayTraces() {// more test data: http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibtable.htmllong results[] = { 0L, 1L, 1L, 2L, 3L, 5L, 8L, 13L };for (int inputValue = 0; inputValue < results.length; inputValue++) {final FibonacciTaskTraces task = new FibonacciTaskTraces(inputValue, " | ");System.out.println("invoke Fibonacci(" + inputValue + ")  <- " + Thread.currentThread().getName());final long result = pool.invoke(task);System.out.println("result = " + result + "\n");Assert.assertEquals(results[inputValue], result);}}
}

// FibonacciTaskTracesTest.java的输出

invoke Fibonacci(0)  <- mainresult = 0invoke Fibonacci(1)  <- mainresult = 1invoke Fibonacci(2)  <- mainresult = 1invoke Fibonacci(3)  <- main|  - Fibonacci(2) <- ForkJoinPool-1-worker-1 (fork) |  - Fibonacci(1) <- ForkJoinPool-1-worker-1|  - Fibonacci(3) = 2 <- ForkJoinPool-1-worker-1 (join)result = 2invoke Fibonacci(4)  <- main|  - Fibonacci(3) <- ForkJoinPool-1-worker-1 (fork) |  - Fibonacci(2) <- ForkJoinPool-1-worker-1|  |  - Fibonacci(2) <- ForkJoinPool-1-worker-2 (fork) |  |  - Fibonacci(1) <- ForkJoinPool-1-worker-2|  |  - Fibonacci(3) = 2 <- ForkJoinPool-1-worker-2 (join)|  - Fibonacci(4) = 3 <- ForkJoinPool-1-worker-1 (join)result = 3invoke Fibonacci(5)  <- main|  - Fibonacci(4) <- ForkJoinPool-1-worker-1 (fork) |  - Fibonacci(3) <- ForkJoinPool-1-worker-1|  |  - Fibonacci(2) <- ForkJoinPool-1-worker-1 (fork) |  |  - Fibonacci(1) <- ForkJoinPool-1-worker-1|  |  - Fibonacci(3) <- ForkJoinPool-1-worker-2 (fork) |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-2|  |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-2 (fork) |  |  |  - Fibonacci(1) <- ForkJoinPool-1-worker-2|  |  - Fibonacci(3) = 2 <- ForkJoinPool-1-worker-1 (join)|  |  |  - Fibonacci(3) = 2 <- ForkJoinPool-1-worker-2 (join)|  |  - Fibonacci(4) = 3 <- ForkJoinPool-1-worker-2 (join)|  - Fibonacci(5) = 5 <- ForkJoinPool-1-worker-1 (join)result = 5invoke Fibonacci(6)  <- main|  - Fibonacci(5) <- ForkJoinPool-1-worker-1 (fork) |  - Fibonacci(4) <- ForkJoinPool-1-worker-1|  |  - Fibonacci(3) <- ForkJoinPool-1-worker-1 (fork) |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-1|  |  - Fibonacci(4) <- ForkJoinPool-1-worker-2 (fork) |  |  - Fibonacci(3) <- ForkJoinPool-1-worker-2|  |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-2 (fork) |  |  |  - Fibonacci(1) <- ForkJoinPool-1-worker-2|  |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-1 (fork) |  |  |  - Fibonacci(1) <- ForkJoinPool-1-worker-1|  |  |  - Fibonacci(3) = 2 <- ForkJoinPool-1-worker-2 (join)|  |  |  - Fibonacci(3) = 2 <- ForkJoinPool-1-worker-1 (join)|  |  |  - Fibonacci(3) <- ForkJoinPool-1-worker-2 (fork) |  |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-2|  |  - Fibonacci(4) = 3 <- ForkJoinPool-1-worker-1 (join)|  |  |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-2 (fork) |  |  |  |  - Fibonacci(1) <- ForkJoinPool-1-worker-2|  |  |  |  - Fibonacci(3) = 2 <- ForkJoinPool-1-worker-2 (join)|  |  |  - Fibonacci(4) = 3 <- ForkJoinPool-1-worker-2 (join)|  |  - Fibonacci(5) = 5 <- ForkJoinPool-1-worker-2 (join)|  - Fibonacci(6) = 8 <- ForkJoinPool-1-worker-1 (join)result = 8invoke Fibonacci(7)  <- main|  - Fibonacci(6) <- ForkJoinPool-1-worker-1 (fork) |  - Fibonacci(5) <- ForkJoinPool-1-worker-1|  |  - Fibonacci(4) <- ForkJoinPool-1-worker-1 (fork) |  |  - Fibonacci(3) <- ForkJoinPool-1-worker-1|  |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-1 (fork) |  |  |  - Fibonacci(1) <- ForkJoinPool-1-worker-1|  |  - Fibonacci(5) <- ForkJoinPool-1-worker-2 (fork) |  |  - Fibonacci(4) <- ForkJoinPool-1-worker-2|  |  |  - Fibonacci(3) <- ForkJoinPool-1-worker-2 (fork) |  |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-2|  |  |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-2 (fork) |  |  |  |  - Fibonacci(1) <- ForkJoinPool-1-worker-2|  |  |  - Fibonacci(3) = 2 <- ForkJoinPool-1-worker-1 (join)|  |  |  - Fibonacci(3) <- ForkJoinPool-1-worker-1 (fork) |  |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-1|  |  |  |  - Fibonacci(3) = 2 <- ForkJoinPool-1-worker-2 (join)|  |  |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-1 (fork) |  |  |  |  - Fibonacci(1) <- ForkJoinPool-1-worker-1|  |  |  - Fibonacci(4) = 3 <- ForkJoinPool-1-worker-2 (join)|  |  |  - Fibonacci(4) <- ForkJoinPool-1-worker-2 (fork) |  |  |  - Fibonacci(3) <- ForkJoinPool-1-worker-2|  |  |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-2 (fork) |  |  |  |  - Fibonacci(1) <- ForkJoinPool-1-worker-2|  |  |  |  - Fibonacci(3) = 2 <- ForkJoinPool-1-worker-1 (join)|  |  |  - Fibonacci(4) = 3 <- ForkJoinPool-1-worker-1 (join)|  |  |  |  - Fibonacci(3) = 2 <- ForkJoinPool-1-worker-2 (join)|  |  - Fibonacci(5) = 5 <- ForkJoinPool-1-worker-1 (join)|  |  |  |  - Fibonacci(3) <- ForkJoinPool-1-worker-2 (fork) |  |  |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-2|  |  |  |  |  - Fibonacci(2) <- ForkJoinPool-1-worker-1 (fork) |  |  |  |  |  - Fibonacci(1) <- ForkJoinPool-1-worker-1|  |  |  |  |  - Fibonacci(3) = 2 <- ForkJoinPool-1-worker-1 (join)|  |  |  |  - Fibonacci(4) = 3 <- ForkJoinPool-1-worker-2 (join)|  |  |  - Fibonacci(5) = 5 <- ForkJoinPool-1-worker-2 (join)|  |  - Fibonacci(6) = 8 <- ForkJoinPool-1-worker-2 (join)|  - Fibonacci(7) = 13 <- ForkJoinPool-1-worker-1 (join)result = 13

现在,输出使您可以更深入地了解程序的处理。 出现以下斐波纳契数计算方法:

  • 前三个斐波那契数在主线程中处理,
  • 下一个斐波那契数仅在一个新线程(ForkJoinPool-1-worker-1)中处理,并且
  • 从第五个斐波纳契数开始,使用了两个线程(ForkJoinPool-1-worker-1和ForkJoinPool-1-worker-2)。

该算法效率低下,因为在处理中存在很多冗余操作(重新计算相同的斐波那契数)。 在现实生活中的应用中,您应该小心使用这种效率低下的算法。 一些痕迹有助于了解发生了什么。

推荐品

  1. 使用fork和join既简单又直接,但是要花一些时间来跟踪和理解您的实现。
  2. 有时实现同一算法的两个版本(一个用于分析,另一个用于生产)会有所帮助。
  3. 花一些时间来设计和理解更好的并发算法是一项不错的投资。

以此方式开发了概率计算器 ( 概率计算器演示– PCALC )。

参考: 如何在Java 7 – JSR 166并发实用程序中实现fork and join? 由我们的JCG合作伙伴 Markus Sprunck在Software Engineering Candies博客上获得。


翻译自: https://www.javacodegeeks.com/2012/04/fork-and-join-in-java-7-jsr-166.html

java jsr

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

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

相关文章

python标准库模块_Python标准库模块之heapq

该模块提供了堆排序算法的实现。堆是二叉树&#xff0c;最大堆中父节点大于或等于两个子节点&#xff0c;最小堆父节点小于或等于两个子节点。 创建堆 heapq有两种方式创建堆&#xff0c; 一种是使用一个空列表&#xff0c;然后使用heapq.heappush()函数把值加入堆中&#xff0…

quartz Cron-Expression的表达式

关于quartz Cron-Expression的表达式&#xff0c;这个博客写的很好 ttp://www.cnblogs.com/yaowen/p/3779284.html CronTrigger配置完整格式为&#xff1a; [秒] [分] [小时] [日] [月] [周] [年] Q&#xff1a; C# quartz设置job间隔5min执行一次 A:0 30/5 16 * * ? 每…

oracle 启用闪回数据库,如何启用Oracle10g闪回数据库特性

为什么80%的码农都做不了架构师&#xff1f;>>>1.确认当前模式SYS AS SYSDBA on 29-MAR-05 >select flashback_on from v$database;FLA---NO2.检查/修改恢复区设置SYS AS SYSDBA on 29-MAR-05 >show parameter db_recovery_file_destNAME TYPE VALUE-----------…

nvme通用驱动_对领域驱动设计的理解与实践

领域驱动设计(Domain-Driven-Design)是一种针对大型复杂系统的领域建模与分析方法论。2003 年&#xff0c;Eric Evans 发布《Domain-Driven Design: Tackling Complexity in the Heart of Software》(领域驱动设计&#xff1a;软件核心复杂性应对之道)&#xff0c;其中定义了DD…

为什么不应该用Stream forEach替换for循环的3个原因

太棒了&#xff01; 我们正在将代码库迁移到Java8。我们将用函数替换所有内容。 扔掉设计模式。 删除面向对象。 对&#xff01; 我们走吧&#xff01; 等一下 Java 8已经问世了一年多&#xff0c;而这种兴奋又回到了日常业务中。 baeldung.com从2015年5月开始执行的一项非代…

Obj文件格式

obj文件是wavefront公司定义的3d模型文本格式数据文件 只支持模型三角面数据和材质信息&#xff0c;无动画功能支持 其中几何信息由.obj文件提供&#xff0c;材质信息由.mtl文件定义 文件以行为单位表示一条数据&#xff0c;可以根据行开头的字符判断后续的内容 其中 # 字符表示…

python通讯录综合_Python通讯录作业

我知道你们懒,代码直接贴到下面了&#xff0c;附上流程图#通讯录管理 #coding:utf-8 Mail{} print( ——————通讯录————— |1.添加联系人 | |2.删除联系人 | |3.查询联系人 | |4.更新联系人 | |5.退出通讯录 | ________________ ) while True: bhinput(请输入编号选择对…

使用NPOI库导入导出EXCEL

一、EXCEL 导入&#xff08;Excel 导入导出实际项目中会被封装成**Helper 本示例只对简单功能做演示&#xff09; NPOI 包引用 视图view {ViewBag.Title "NPOIExcel"; }<h2>NPOIExcel</h2> <form action"Url.Action("NPOIInport", &…

oracle12c ora 12547,Oracle 12c DBCA出现PRCR-1079 ORA-12547 CRS-5017

Oracle 12c用dbca创建数据库时出现了PRCR-1079 ORA-12547 CRS-5017不能启动数据库。因为这里安装了Oracle Restart&#xff0c;所以尝试使用srvctl start database命令来手动启动数据库&#xff0c;但是结果还是一样不能启动。[gridoracle12c 12.1]$ srvctl start database -db…

kmeans鸢尾花分类python代码_python实现鸢尾花三种聚类算法(K-means,AGNES,DBScan)

一.分散性聚类(kmeans) 算法流程: 1.选择聚类的个数k. 2.任意产生k个聚类&#xff0c;然后确定聚类中心&#xff0c;或者直接生成k个中心。 3.对每个点确定其聚类中心点。 4.再计算其聚类新中心。 5.重复以上步骤直到满足收敛要求。&#xff08;通常就是确定的中心点不再改变。…

akka_Akka的字数统计MapReduce

akka在我与Akka的日常工作中&#xff0c;我最近写了一个字数映射减少示例。 本示例实现了Map Reduce模型&#xff0c;该模型非常适合横向扩展设计方法。 流 客户端系统&#xff08;FileReadActor&#xff09;读取文本文件&#xff0c;并将每一行文本作为消息发送给ClientActor…

Log4j 2配置与IntelliJ IDEA控制台颜色

Log4j是Java平台上最好的日志组件了&#xff0c;Log4j 2升级了不少API&#xff0c;拓展性更好。使用的话只需要直接引入就可以了. <dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version> &…

用c3p0连接oracle怎么分页,JSP分页(MySql+c3p0+dbutils)

JSP分页(MySqlc3p0dbutils)来源&#xff1a;互联网作者&#xff1a;佚名时间&#xff1a;2015-02-16 17:27为什么要对数据进行分页&#xff1f;当数据较多时&#xff0c;页面就会变的很庞大&#xff0c;不仅会影响到用户的使用&#xff0c;而且还有加重服务器的负担。下面简单的…

用python自动发邮件_Python实现向QQ群成员自动发邮件的方法

#coding:utf-8 import random import smtplib from email.mime.text import MIMEText import time def send_mail(mailto): print Setting MIMEText CTopen(content.txt,r) #读取发送邮件内容 contentCT.read().decode(utf-8) msgMIMEText(content.encode(utf8),_subtypehtml) …

Apache Storm的实时情绪分析示例

实时情感分析是指处理自然语言文本&#xff08;或语音&#xff09;流以提取主观信息。 琐碎的用例用于构建推荐引擎或查找社交媒体趋势。 我选择了Apache Storm作为实时处理引擎。 Storm非常强大&#xff08;我们正在生产中使用它&#xff09;&#xff0c;并且非常容易在其之上…

产品经理在早期如何快速学习?

产品经理在早期如何快速学习&#xff1f; 1、多阅读 &#xff08;1&#xff09;阅读专业书籍 比如说小米的黎万强写了一本《参与感》&#xff0c;讲述了小米成长过程中的一系列案例分析&#xff0c;概念总结。黎老师是小米创始元老&#xff0c;案例有小米的成功背书&#xff0c…

linux ftp解压命令 cannot fid or open,Linux环境搭建及常用shell命令集锦

22.crontab –l 查看crontab命令行 (13)23.重定向 (13)24.ps –eaf | grep httpd 查找httpd进程 (13)25.kill -9 PID 强制停止进程 (13)26.rpm –ivh a.rpm 安装rpm包 (13)27.chmod 111(可执行)/222(可读)/444(可写) file 权限 (13)28.修改linux颜色在vim .bash_profile里添加e…

flink sql设置并行度_《从0到1学习Flink》—— Flink parallelism 和 Slot 介绍

前言之所以写这个是因为前段时间自己的项目出现过这样的一个问题&#xff1a;Caused by: akka.pattern.AskTimeoutException: Ask timed out on [Actor[akka://flink/user/taskmanager_0#15608456]] after [10000 ms]. Sender[null] sent message of type "org.apache.f…

zabbix3.2监控

自动化运维框架 运维标准流程监控管理容量管理、关联关系、任务管理、自动部署、分布式集群、传统集群、机器管理安全控制灾难管理 自动化监控 监控评估数据采集主动式数据采集: client、公共插件、自定义脚本被动式服务状态: 服务状态、程序状态、用户访问质量第三方信息 公…

linux使用创建es用户,linux用户权限设置(安装elasticsearch7.x)

前言今天下载了elasticsearch的7.x版本&#xff0c;使用bin/elasticsearch -d 启动后&#xff0c;报出如下错误&#xff1a;java.lang.RuntimeException: can not run elasticsearch as rootat org.elasticsearch.bootstrap.Bootstrap.initializeNatives(Bootstrap.java:105)at…