java之Fork/Join框架
创始人
2024-01-21 02:29:40

文章目录

    • 前言
    • 工作窃取算法
    • Fork/Join框架的设计
    • Fork/Join框架的异常处理
    • Fork/Join框架的实现原理
    • 总结

前言

Fork/Join框架是java7提供的一个用于执行并行任务的框架,是一个把大部分任务分割成若干个小任务,最终汇总每个小任务结果后,得到大任务结果的框架。

工作窃取算法

工作窃取算法是指某个线程从其他队列里窃取任务来执行。为什么要使用这个工作窃取算法呢。首先Fork/Join框架是把一个大任务分为了好多个子任务,然后把这些子任务,交给不同的线程去执行。这个时候就会有一个问题。不同的线程,执行的速度肯定是不一样的,有的线程执行的快,有的线程执行的慢,这个就会导致有的线程任务已经执行完了,但是有的线程,还会有很多的任务。但是执行完任务的线程,也不能空着啊,不然就是浪费效率。所以,这个时候就会用到工作窃取算法,做完任务的线程,会去没做完任务的线程那里,窃取一些线程,来进行工作。如下图,是工作窃取算法的运行流程图。
在这里插入图片描述
线程1为做完任务的线程,它窃取线程2的线程的时候,是从尾部窃取的。线程2 是被窃取的线程,它是从头部取线程的。

工作窃取算法的缺点:在某些情况下还是存在竞争的,比如在双端队列里只有一个任务的时候。并且该线程消耗了更多的系统资源,比如创建了多个线程和多个双端队列。

Fork/Join框架的设计

Fork/Join框架的设计总体大致分为两个步骤
1.分割任务。首先需要一个fork类把大任务分割为子任务,有可能子任务还是很大,所以需要不停的分割,直到分割出的子任务足够小。
2.执行任务并合并结果: 分割的子任务放在双端队列里面,然后创建多线程去双端队列里面拿任务执行。子任务的结果统一放在一个队列里面,启动一个线程从队列里面拿数据,然后合并这些数据。

Fork/Join框架的异常处理

ForkJoinTask在执行的时候可能会抛出异常,但是我们没办法在主线程里直接捕获异常,所以ForkJoinTask提供了isCompletedAbnormally()方法来检查任务是否抛出异常或已经被取消了,并且可以通过ForkJoinTask的getException方法捕获异常。

Fork/Join框架的实现原理

ForkJoinPool由ForkJoinTask数组和ForkJoinWorkerThread数组组成。ForkJoinTask数组负责将存放程序提交给ForkJoinPool的任务,而ForkJoinWorkerThread数组负责执行这些任务。

1.ForkJoinTask的fork方法实现原理
当我们调用ForkJoinTask的fork方法时,程序会调用ForkJoinWorkerThread的push方法异步的执行这个任务(就是把任务都放到队列里面),然后立即返回结果。代码如下:

  public final ForkJoinTask fork() {Thread t;if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)((ForkJoinWorkerThread)t).workQueue.push(this);elseForkJoinPool.common.externalPush(this);return this;}

push方法会把当前任务存放在ForkJoinTask数组队列里。然后调用ForkJoinPool的signalWork()方法唤醒或创建一个工作线程来执行任务。

final void push(ForkJoinTask task) {ForkJoinTask[] a; ForkJoinPool p;int b = base, s = top, n;if ((a = array) != null) {    // ignore if queue removedint m = a.length - 1;     // fenced write for task visibilityU.putOrderedObject(a, ((m & s) << ASHIFT) + ABASE, task);U.putOrderedInt(this, QTOP, s + 1);if ((n = s - b) <= 1) {if ((p = pool) != null)p.signalWork(p.workQueues, this);}else if (n >= m)growArray();}
}

2.ForkJoinTask的join方法主要作用时阻塞当前线程,并等待获取结果

public final V join() {int s;if ((s = doJoin() & DONE_MASK) != NORMAL)reportException(s);return getRawResult();
}
private int doJoin() {int s; Thread t; ForkJoinWorkerThread wt; ForkJoinPool.WorkQueue w;return (s = status) < 0 ? s :((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?(w = (wt = (ForkJoinWorkerThread)t).workQueue).tryUnpush(this) && (s = doExec()) < 0 ? s :wt.pool.awaitJoin(w, this, 0L) :externalAwaitDone();
}

这里我们就不详细的介绍源码了,内容太多了,我这里说下这段代码的大概意思。大致就是通过dojoin方法得到当前任务状态,然后根据任务状态,来判断返回什么结果。

总结

这种拆分的思想十分的常见,大数据中的mapreduce,采用的也是这种思想。都是将一个大的任务分为小的任务,然后计算每个小任务的结果,最后合并。因此,当我们在java中遇到一个十分的复杂的任务的时候,不妨考虑下使用Fork/Join框架。

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
进口奶粉的排名 荷兰奶粉十大排... 越来越乱的国内奶粉市场让很多宝妈宝爸都不知道该如何选择奶粉品牌,宝宝的安全是第一位,奶粉的质量以及口...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
不用扬鞭自奋蹄 乘势而上千帆竞... 思明区正全力向“两个进位”目标发起冲刺,努力为建设高素质高颜值现代化国际化的厦门作出“思明贡献”。(...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...