Java7任务并行执行神器:Fork&Join框架

2018年01月12日 17:25:03
Java技术栈
阅读数:426

													<span class="tags-box artic-tag-box">
<span class="label">标签:</span>
<a data-track-click="{&quot;mod&quot;:&quot;popu_626&quot;,&quot;con&quot;:&quot;JAVA&quot;}" class="tag-link" href="http://so.csdn.net/so/search/s.do?q=JAVA&amp;t=blog" target="_blank">JAVA </a><a data-track-click="{&quot;mod&quot;:&quot;popu_626&quot;,&quot;con&quot;:&quot;FORKJOIN&quot;}" class="tag-link" href="http://so.csdn.net/so/search/s.do?q=FORKJOIN&amp;t=blog" target="_blank">FORKJOIN </a>
<span class="article_info_click">更多</span></span>
<div class="tags-box space">
<span class="label">个人分类:</span>
<a class="tag-link" href="https://blog.csdn.net/youanyyou/article/category/695509" target="_blank">Java </a>
</div>
</div>
<div class="operating">
</div>
</div>
</div>
</div>
<article>
<div id="article_content" class="article_content clearfix csdn-tracking-statistics" data-pid="blog" data-mod="popu_307" data-dsm="post">
<div class="article-copyright">
版权声明:转载请注明原文链接,非法转载者将追究其法律责任。 https://blog.csdn.net/youanyyou/article/details/78990280 </div>
<div class="markdown_views">
<!-- flowchart 箭头图标 勿删 -->
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path></svg>
<h4 id="forkjoin是什么">Fork/Join是什么?</h4>

Fork/Join框架是Java7提供的并行执行任务框架,思想是将大任务分解成小任务,然后小任务又可以继续分解,然后每个小任务分别计算出结果再合并起来,最后将汇总的结果作为大任务结果。其思想和MapReduce的思想非常类似。对于任务的分割,要求各个子任务之间相互独立,能够并行独立地执行任务,互相之间不影响。

Fork/Join的运行流程图如下:

我们可以通过Fork/Join单词字面上的意思去理解这个框架。Fork是叉子分叉的意思,即将大任务分解成并行的小任务,Join是连接结合的意思,即将所有并行的小任务的执行结果汇总起来。

工作窃取算法

ForkJoin采用了工作窃取(work-stealing)算法,若一个工作线程的任务队列为空没有任务执行时,便从其他工作线程中获取任务主动执行。为了实现工作窃取,在工作线程中维护了双端队列,窃取任务线程从队尾获取任务,被窃取任务线程从队头获取任务。这种机制充分利用线程进行并行计算,减少了线程竞争。但是当队列中只存在一个任务了时,两个线程去取反而会造成资源浪费。

工作窃取的运行流程图如下:

Fork/Join核心类

Fork/Join框架主要由子任务、任务调度两部分组成,类层次图如下。

  • ForkJoinPool

ForkJoinPool是ForkJoin框架中的任务调度器,和ThreadPoolExecutor一样实现了自己的线程池,提供了三种调度子任务的方法:

  1. execute:异步执行指定任务,无返回结果;
  2. invoke、invokeAll:异步执行指定任务,等待完成才返回结果;
  3. submit:异步执行指定任务,并立即返回一个Future对象;

    • ForkJoinTask

Fork/Join框架中的实际的执行任务类,有以下两种实现,一般继承这两种实现类即可。

  1. RecursiveAction:用于无结果返回的子任务;
  2. RecursiveTask:用于有结果返回的子任务;

Fork/Join框架实战

下面实现一个Fork/Join小例子,从1+2+…10亿,每个任务只能处理1000个数相加,超过1000个的自动分解成小任务并行处理;并展示了通过不使用Fork/Join和使用时的时间损耗对比。

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask; public class ForkJoinTask extends RecursiveTask<Long> { private static final long MAX = 1000000000L;
private static final long THRESHOLD = 1000L;
private long start;
private long end; public ForkJoinTask(long start, long end) {
this.start = start;
this.end = end;
} public static void main(String[] args) {
test();
System.out.println("--------------------");
testForkJoin();
} private static void test() {
System.out.println("test");
long start = System.currentTimeMillis();
Long sum = 0L;
for (long i = 0L; i <= MAX; i++) {
sum += i;
}
System.out.println(sum);
System.out.println(System.currentTimeMillis() - start + "ms");
} private static void testForkJoin() {
System.out.println("testForkJoin");
long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
Long sum = forkJoinPool.invoke(new ForkJoinTask(1, MAX));
System.out.println(sum);
System.out.println(System.currentTimeMillis() - start + "ms");
} @Override
protected Long compute() {
long sum = 0;
if (end - start <= THRESHOLD) {
for (long i = start; i <= end; i++) {
sum += i;
}
return sum;
} else {
long mid = (start + end) / 2; ForkJoinTask task1 = new ForkJoinTask(start, mid);
task1.fork(); ForkJoinTask task2 = new ForkJoinTask(mid + 1, end);
task2.fork(); return task1.join() + task2.join();
}
} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

这里需要计算结果,所以任务继承的是RecursiveTask类。ForkJoinTask需要实现compute方法,在这个方法里首先需要判断任务是否小于等于阈值1000,如果是就直接执行任务。否则分割成两个子任务,每个子任务在调用fork方法时,又会进入compute方法,看看当前子任务是否需要继续分割成孙任务,如果不需要继续分割,则执行当前子任务并返回结果。使用join方法会阻塞并等待子任务执行完并得到其结果。

程序输出:

test
500000000500000000
4992ms
--------------------
testForkJoin
500000000500000000
508ms
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

从结果看出,并行的时间损耗明显要少于串行的,这就是并行任务的好处。

尽管如此,在使用Fork/Join时也得注意,不要盲目使用。

  1. 如果任务拆解的很深,系统内的线程数量堆积,导致系统性能性能严重下降;
  2. 如果函数的调用栈很深,会导致栈内存溢出;

推荐阅读

干货:免费领取2TB架构师四阶段视频教程

面经:史上最全Java多线程面试题及答案

工具:推荐一款在线创作流程图、思维导图软件

分享Java干货,高并发编程,热门技术教程,微服务及分布式技术,架构设计,区块链技术,人工智能,大数据,Java面试题,以及前沿热门资讯等。

				<script>
(function(){
function setArticleH(btnReadmore,posi){
var winH = $(window).height();
var articleBox = $("div.article_content");
var artH = articleBox.height();
if(artH > winH*posi){
articleBox.css({
'height':winH*posi+'px',
'overflow':'hidden'
})
btnReadmore.click(function(){
articleBox.removeAttr("style");
$(this).parent().remove();
})
}else{
btnReadmore.parent().remove();
}
}
var btnReadmore = $("#btn-readmore");
if(btnReadmore.length>0){
if(currentUserName){
setArticleH(btnReadmore,3);
}else{
setArticleH(btnReadmore,1.2);
}
}
})()
</script>
</article>
posted @
2018-10-31 10:03 
jobs-lgy 
阅读(...) 
评论(...) 
编辑 
收藏

Java7任务并行执行神器:Fork&Join框架的更多相关文章

  1. 013-多线程-基础-Fork/Join框架、parallelStream讲解

    一.概述 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 它同ThreadPoolExecut ...

  2. Java并发编程--Fork/Join框架使用

    上篇博客我们介绍了通过CyclicBarrier使线程同步,可是上述方法存在一个问题,那就是假设一个大任务跑了2个线程去完毕.假设线程2耗时比线程1多2倍.线程1完毕后必须等待线程2完毕.等待的过程线 ...

  3. Fork/Join框架与Java8 Stream API 之并行流的速度比较

    Fork/Join 框架有特定的ExecutorService和线程池构成.ExecutorService可以运行任务,并且这个任务会被分解成较小的任务,它们从线程池中被fork(被不同的线程执行)出 ...

  4. Java7任务并行执行神器:Fork&Join框架

    Fork/Join是什么? Fork/Join框架是Java7提供的并行执行任务框架,思想是将大任务分解成小任务,然后小任务又可以继续分解,然后每个小任务分别计算出结果再合并起来,最后将汇总的结果作为 ...

  5. 使用Java7提供Fork/Join框架

    在Java7在.JDK它提供了多线程开发提供了一个非常强大的框架.这是Fork/Join框架.这是原来的Executors更多 进一步,在原来的基础上添加了并行分治计算中的一种Work-stealin ...

  6. 使用Java7提供的Fork/Join框架

    http://blog.csdn.net/a352193394/article/details/39872923 使用Java7提供的Fork/Join框架 2014-10-07 23:55 4818 ...

  7. 多线程(五) Fork/Join框架介绍及实例讲解

    什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过For ...

  8. JAVA中的Fork/Join框架

    看了下Java Tutorials中的fork/join章节,整理下. 什么是fork/join框架 fork/join框架是ExecutorService接口的一个实现,可以帮助开发人员充分利用多核 ...

  9. 聊聊并发(八)——Fork/Join框架介绍

      作者 方腾飞 发布于 2013年12月23日 | 被首富的“一个亿”刷屏?不如定个小目标,先把握住QCon上海的优惠吧!2 讨论 分享到:微博微信FacebookTwitter有道云笔记邮件分享 ...

随机推荐

  1. 使用vue实现复选框单选多选

    界面样式: <div class="right_con" v-if="isClickApply" style="border:none" ...

  2. Visual Studio 2015创建ASP.NET MVC流程

    本文链接:https://blog.csdn.net/begindong/article/details/68059437本人这两天第一次对c#进行系统学习,写出来做个学习记录和大家分享,以下有什么错 ...

  3. vue中mixins的理解及应用

    vue中mixins的理解及应用 vue中提供了一种混合机制--mixins,用来更高效的实现组件内容的复用.最开始我一度认为这个和组件好像没啥区别..后来发现错了.下面我们来看看mixins和普通情 ...

  4. Light Up Your Business Promotions With LED Keychain

    Imagine you want to insert the car key into the keyhole in the dark. What would you do? You will def ...

  5. FIR滤波器工作原理(算法)以及verilog算法实现(包含与IIR的一些对比)

    滤波器在2017年IC前端的笔试中,出现频率十分的高.不论今后是否会涉及,还是要记住一些会比较好.接下来就将从这四个方面来讲解,FIR数字滤波器的工作原理(算法)与verilog实现. ·什么是FIR ...

  6. 浅谈DAO工厂设计模式(工厂模式的好处)

    随着软件分层设计的流行及广泛的应用,对于DAO的设计模式大家已经不再陌生了,DAO层已经在软件系统的开发中成为必不可少的一层,将后台的数据层和前台的VO进行分离.前段时间也针对于DAO的设计介绍过一个 ...

  7. 8.10-Day1T1-数字(number)

    数字number 题目大意 给定n,k,s,从1到n中取出k个数,使其之和等于s 求可行的方案数(模1e9+7) 题解 一眼dp,于是我去写了dfs,带着少的可怜的剪枝,快乐的tle着... 设 f[ ...

  8. 计算几何-poj2451-HPI

    This article is made by Jason-Cow.Welcome to reprint.But please post the article's address. 题意,求半平面交 ...

  9. bugku flag在index里

    原题内容: http://120.24.86.145:8005/post/ Mark一下这道题,前前后后弄了两个多小时,翻了一下别的博主的wp感觉还是讲的太粗了,这里总结下自己的理解: 首先打开这道题 ...

  10. pgspider http fdw http 相关的几个配置参数

    http 请求时间配置 session 级别的 set http.timeout_msec = 10000; SELECT http_set_curlopt('CURLOPT_TIMEOUT', '1 ...