java中fork函数_java中的forkjoin框架的使用

42bd13c6670274f0993c5c92419dc87e.png

fork join框架是java 7中引入框架,这个框架的引入主要是为了提升并行计算的能力。

fork join主要有两个步骤,第一就是fork,将一个大任务分成很多个小任务,第二就是join,将第一个任务的结果join起来,生成最后的结果。如果第一步中并没有任何返回值,join将会等到所有的小任务都结束。

还记得之前的文章我们讲到了thread pool的基本结构吗?

ExecutorService - ForkJoinPool 用来调用任务执行。

workerThread - ForkJoinWorkerThread 工作线程,用来执行具体的任务。

task - ForkJoinTask 用来定义要执行的任务。

下面我们从这三个方面来详细讲解fork join框架。

ForkJoinPool

ForkJoinPool是一个ExecutorService的一个实现,它提供了对工作线程和线程池的一些便利管理方法。

public class ForkJoinPool extends AbstractExecutorService

一个work thread一次只能处理一个任务,但是ForkJoinPool并不会为每个任务都创建一个单独的线程,它会使用一个特殊的数据结构double-ended queue来存储任务。这样的结构可以方便的进行工作窃取(work-stealing)。

什么是work-stealing呢?

默认情况下,work thread从分配给自己的那个队列头中取出任务。如果这个队列是空的,那么这个work thread会从其他的任务队列尾部取出任务来执行,或者从全局队列中取出。这样的设计可以充分利用work thread的性能,提升并发能力。

下面看下怎么创建一个ForkJoinPool。

最常见的方法就是使用ForkJoinPool.commonPool()来创建,commonPool()为所有的ForkJoinTask提供了一个公共默认的线程池。

ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();

另外一种方式是使用构造函数:

ForkJoinPool forkJoinPool = new ForkJoinPool(2);

这里的参数是并行级别,2指的是线程池将会使用2个处理器核心。

ForkJoinWorkerThread

ForkJoinWorkerThread是使用在ForkJoinPool的工作线程。

public class ForkJoinWorkerThread extends Thread

}

和一般的线程不一样的是它定义了两个变量:

final ForkJoinPool pool; // the pool this thread works in

final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics

一个是该worker thread所属的ForkJoinPool。 另外一个是支持 work-stealing机制的Queue。

再看一下它的run方法:

public void run() {

if (workQueue.array == null) { // only run once

Throwable exception = null;

try {

onStart();

pool.runWorker(workQueue);

} catch (Throwable ex) {

exception = ex;

} finally {

try {

onTermination(exception);

} catch (Throwable ex) {

if (exception == null)

exception = ex;

} finally {

pool.deregisterWorker(this, exception);

}

}

}

}

简单点讲就是从Queue中取出任务执行。

ForkJoinTask

ForkJoinTask是ForkJoinPool中运行的任务类型。通常我们会用到它的两个子类:RecursiveAction和RecursiveTask。

他们都定义了一个需要实现的compute()方法用来实现具体的业务逻辑。不同的是RecursiveAction只是用来执行任务,而RecursiveTask可以有返回值。

既然两个类都带了Recursive,那么具体的实现逻辑也会跟递归有关,我们举个使用RecursiveAction来打印字符串的例子:

public class CustomRecursiveAction extends RecursiveAction {

private String workload = "";

private static final int THRESHOLD = 4;

private static Logger logger =

Logger.getAnonymousLogger();

public CustomRecursiveAction(String workload) {

this.workload = workload;

}

@Override

protected void compute() {

if (workload.length() > THRESHOLD) {

ForkJoinTask.invokeAll(createSubtasks());

} else {

processing(workload);

}

}

private List createSubtasks() {

List subtasks = new ArrayList<>();

String partOne = workload.substring(0, workload.length() / 2);

String partTwo = workload.substring(workload.length() / 2, workload.length());

subtasks.add(new CustomRecursiveAction(partOne));

subtasks.add(new CustomRecursiveAction(partTwo));

return subtasks;

}

private void processing(String work) {

String result = work.toUpperCase();

logger.info("This result - (" + result + ") - was processed by "

+ Thread.currentThread().getName());

}

}

上面的例子使用了二分法来打印字符串。

我们再看一个RecursiveTask的例子:

public class CustomRecursiveTask extends RecursiveTask {

private int[] arr;

private static final int THRESHOLD = 20;

public CustomRecursiveTask(int[] arr) {

this.arr = arr;

}

@Override

protected Integer compute() {

if (arr.length > THRESHOLD) {

return ForkJoinTask.invokeAll(createSubtasks())

.stream()

.mapToInt(ForkJoinTask::join)

.sum();

} else {

return processing(arr);

}

}

private Collection createSubtasks() {

List dividedTasks = new ArrayList<>();

dividedTasks.add(new CustomRecursiveTask(

Arrays.copyOfRange(arr, 0, arr.length / 2)));

dividedTasks.add(new CustomRecursiveTask(

Arrays.copyOfRange(arr, arr.length / 2, arr.length)));

return dividedTasks;

}

private Integer processing(int[] arr) {

return Arrays.stream(arr)

.filter(a -> a > 10 && a < 27)

.map(a -> a * 10)

.sum();

}

}

和上面的例子很像,不过这里我们需要有返回值。

在ForkJoinPool中提交Task

有了上面的两个任务,我们就可以在ForkJoinPool中提交了:

int[] intArray= {12,12,13,14,15};

CustomRecursiveTask customRecursiveTask= new CustomRecursiveTask(intArray);

int result = forkJoinPool.invoke(customRecursiveTask);

System.out.println(result);

上面的例子中,我们使用invoke来提交,invoke将会等待任务的执行结果。

如果不使用invoke,我们也可以将其替换成fork()和join():

customRecursiveTask.fork();

int result2= customRecursiveTask.join();

System.out.println(result2);

fork() 是将任务提交给pool,但是并不触发执行, join()将会真正的执行并且得到返回结果。

本文的例子可以参考https://github.com/ddean2009/learn-java-concurrency/tree/master/forkjoin

到此这篇关于java中的fork join框架的使用的文章就介绍到这了,更多相关java fork join框架内容请搜索云海天教程以前的文章或继续浏览下面的相关文章希望大家以后多多支持云海天教程!

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

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

相关文章

java中已定义类型car_Java 8 习惯用语(8):Java 知道您的类型

Java™8是第一个支持类型推断的 Java 版本&#xff0c;而且它仅对 lambda 表达式支持此功能。在 lambda表达式中使用类型推断具有强大的作用&#xff0c;它将帮助您做好准备以应对未来的 Java版本&#xff0c;在今后的版本中还会将类型推断用于变量等更多可能。这里的诀窍在于恰…

java web 来源页_Java:Java Web--分页效果

先来看一看分页的实现原理万能公式.jpg项目目录.PNG首先,新建Java Web项目一. 梳理业务逻辑重定向到URL(跳转到StudentViewAction页面)//index.jsp页面1.从页面接收可变的值2.接收值有问题时,初始化为13.如果没有问题,把String类型接收值强转成Integer4.实例DAO方法,调用findSt…

java 浏览器 安全_安全策略-IE浏览器防黑十大秘籍

1.管理好Cookie在IE6.0中&#xff0c;打开“工具”→“Internet选项”→“隐私”对话框&#xff0c;这里设定了“阻止所有Cookie”、“高”、“中高”、“中”、“低”、“接受所有Cookie”六个级别&#xff0c;你只要拖动滑块就可以方便地进行设定&#xff0c;而点击下方的“编…

php截取指定字符串之后,php截取字符串(截取指定字符串之间的字符串)

一、PHP截取两个指定字符后边的字符$a "123abc#456";$b (strpos($a,""));$c (strpos($a,"#"));echo substr($a,$b1,$c-1);二、常用截取字符串技巧。//构造字符串$str "ABCDEFGHIJKLMNOPQRSTUVWXYZ";echo "原字符串&#xff1a;…

php 获取key的位置,PHP获取当前所在目录位置的方法

本文实例讲述了PHP获取当前所在目录位置的方法。分享给大家供大家参考。具体分析如下&#xff1a;如果要获取脚本文件的目录&#xff0c;要应用函数getcwd()来实现。函数声明如下&#xff1a;string getcwd ( void ) ;成功执行后返回当前目录字符串&#xff0c;失败返回FALSE。…

php连接数据库navicat,navicat数据库如何连接php

第一步&#xff0c;打开Navicat&#xff0c;新建数据库。第二步&#xff0c;在数据库中新建表。相关推荐&#xff1a;《Navicat for mysql使用图文教程》第三步&#xff0c;保存表。第四步&#xff0c;表中添加数据。第五步&#xff0c;打开ide&#xff0c;输入以下php代码&…

每日一题:LCR 095.最长公共子序列(DP)

题目描述&#xff1a; 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删除某些…

php自动合并,php实现合并数组并去除重复的方法

php实现合并数组并去除重复的方法发布时间&#xff1a;2020-08-12 10:35:05来源&#xff1a;亿速云阅读&#xff1a;99作者&#xff1a;小新这篇文章主要介绍了php实现合并数组并去除重复的方法&#xff0c;具有一定借鉴价值&#xff0c;需要的朋友可以参考下。希望大家阅读完这…

linux内核运行关系图,一张图看懂Linux内核运行交互关系

很多朋友如果接触过Linux的都知道Kernel的含义&#xff0c;kernel是操作系统的核心或者最重要的部分。众所周知的是&#xff0c;几乎整个互联网都运行在 Linux上&#xff0c;从网络协议&#xff0c;到服务器&#xff0c;到你平常访问的绝大多数网站&#xff0c;都能看到它的身…

linux内核bios,BIOS的启动原理——Linux内核设计学习笔记

RAM&#xff1a;随机存取存储器&#xff0c;常见的内存条就是一类RAM&#xff0c;其特点是加电状态下可任意读、写&#xff0c;断电后信息消失。在RAM中什么程序也没有的时候&#xff0c;谁来完成加载软盘中操作系统的任务呢&#xff1f;答案是&#xff1a;BIOS。BIOS的启动原理…

Linux下仿windows任务管理器,开源任务管理器 Process Hacker (Windows)

Windows表面上没有工作在进行中&#xff0c;但不知为何负荷很重&#xff0c;究竟有什么进程在执行&#xff1f;会不会是系统已经被入侵&#xff1f;这是很多人都想知道的问题。但Windows自带的任务管理员实在太过简陋&#xff0c;解决办法便是安装这次介绍的Process Hacker。熟…

嵌入式linux中的锁机制,跟涛哥一起学嵌入式第11集:一个实现锁机制非常有意思的宏...

QQ群(宅学部落)有位学员问了一个很奇怪的宏&#xff0c;觉得很有意思&#xff0c;特拿来分享&#xff0c;它的定义如下:我们知道&#xff0c;宏定义其实就是为了方便&#xff0c;给一串代码字符串定义一个别名。有时候字符串过于复杂&#xff0c;我们可以分多行书写&#xff0c…

linux core 永久生效,【调试】Core Dump是什么?Linux下如何正确永久开启?

内容简介【调试】Core Dump是什么&#xff1f;Linux下如何正确永久开启&#xff1f;Core Dump是什么&#xff1f;Linux下如何正确永久开启&#xff1f;Core Dump是什么&#xff1f;Core Dump乍听之下很抽象。当程序运行的过程中异常终止或崩溃&#xff0c;操作系统会将程序当时…

用于用户C语言标识符,下列可用于C语言用户标识符的一组是( )

摘要&#xff1a;下列不属于骨肉瘤患者常见护理问题()于C语言用户组Since people send nonverbal signals through multiple channels simultaneously, it is impossible to increase our nonverbal communication competence by becoming more aware of how it operates in sp…

c语言猜四位数游戏猜10次,C语言猜数字游戏--随机生成4个不相同的数字从小到大排序,用户开始游戏,如果用户猜对数字和数字对应的位置,界面回馈A,如果数字正确位置不正确,则回馈B...

1.看程序运行截图吧&#xff01;&#xff01;由于博主本人较笨&#xff0c;就不动画演示了&#xff0c;如果动画的话可能将是一个漫长的过程&#xff01;猜数字游戏.png2.游戏题目随机生成4个不相同的数字从小到大排序&#xff0c;用户开始游戏&#xff0c;如果用户猜对数字和数…

双端堆c语言,数据结构——双端堆(C语言)

定义双端堆&#xff1a;是一棵完全二叉树&#xff0c;该完全二叉树要么为空&#xff0c;要么同时满足下列性质&#xff1a;(1) 根节点不包含元素&#xff1b;(2) 左子树是一个最小堆&#xff1b;(3) 右子树是一个最大堆&#xff1b;(4) 如果右子树不空&#xff0c;令i是左子树中…

C语言和我的世界指令哪个难,我的世界难度有什么区别 难度选择指令介绍

我的世界中的难度(Difficulty)可以在Minecraft的选项菜单内切换。更改这个选项将直接影响到游戏本身。选项中并没有设定影响攻击性生物的可生成数量&#xff0c;包括和平模式。目前游戏共有和平、简单、普通和困难4种难度。我的世界难度区别和平&#xff1a;会生成攻击性生物&a…

w ndows10即将停止更新,微软开始警告Windows 10 v1909用户即将停止更新服务

如果您仍在运行Windows 10版本1909&#xff0c;版本1903或更早版本&#xff0c;则可能已经在系统任务栏中注意到一条新消息&#xff1a;Windows 10版本即将终止服务。根据Windows 10 May 2020 Update或2020年10月Update。为了将用户升级到最新版本的Windows 10&#xff0c;“您…

Android10不能用谷歌,谷歌真的很严格,一大波老APP将不能在安卓10.0运行

苹果iOS的一大优点就是软件生态&#xff0c;第三方APP都会主动适配新的iOS系统以及手机。虽然说Android的开放性是也是一大优点&#xff0c;但是第三方软件参差不齐的优化适配水平也让安卓的用户非常头疼。不过谷歌每年都在致力于让Android的软件生态更好。根据XDA的报道&#…

c语言编程季节输出春夏秋冬,c语言编程题: 用枚类型定义春、夏、秋、冬四个季节...

满意答案bcabcdefg2013.07.28采纳率&#xff1a;49% 等级&#xff1a;12已帮助&#xff1a;5373人#includeenum season{spring 1,summer,autumn,winter,};season GetSeasonByMonth(char month){if(month < 3 && month>1)return spring;else if(month < 6 …