首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >关于堆栈使用的java Fork/Join说明

关于堆栈使用的java Fork/Join说明
EN

Stack Overflow用户
提问于 2012-06-29 21:13:29
回答 3查看 1.5K关注 0票数 18

我读到了Java 7中引入的Fork/Join框架的实现,我只是想检查一下我是否理解了这个魔术是如何工作的。

据我所知,当一个线程派生时,它会在它的队列中创建子任务(其他线程可能窃取,也可能不窃取)。当线程尝试" join“时,它实际上检查现有任务的队列,然后递归地执行它们,这意味着对于任何-2\f25 'join‘操作,-2\f25 frames 2\f6将被添加到线程调用堆栈中(一个用于join,另一个用于新执行的任务调用)。

因为我知道JVM不支持尾部调用优化(在这种情况下可以用来删除连接方法堆栈框架),我认为在执行包含大量分叉和连接的复杂操作时,线程可能会抛出StackOverflowError

我是对的,还是他们找到了一些很酷的方法来阻止它?

编辑

这里有一个场景来帮助澄清这个问题:假设(为简单起见)我们在forkjoin池中只有一个线程。在某个时间点-线程分叉,然后调用join。而在join方法中,线程发现它可以执行forked任务(就像它在队列中发现的那样),所以它调用下一个任务。该任务依次派生,然后调用join -因此,在执行join方法时,线程将在其队列中找到派生的任务(就像前面一样)并调用它。在该阶段,调用堆栈将至少包含两个连接和两个任务的帧。

正如您所看到的,fork join框架转换为普通递归。因为java不支持尾部调用优化-如果java中的每一次递归都足够深入,就会导致StackOverflowError

我的问题是- fork/join框架的实现者是否找到了一些很酷的方法来防止这种情况。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-07-06 05:26:04

不幸的是,在线程递归堆栈方面并没有什么神奇的事情发生。如果你的初始任务分叉/拆分,并且没有一个合理的解决点,那么你就会遇到StackOverflowErrors。

您也许可以理解为什么JavaDoc教程会将每个子任务一分为二。

票数 8
EN

Stack Overflow用户

发布于 2012-06-29 22:15:09

通常,推送到堆栈上的每个新任务的大小都是前一个任务的一半。因此,工作量随着堆栈大小呈指数增长。即使只有一个很小的堆栈,您也能够完成足够多的工作来让您忙碌一段时间。

票数 2
EN

Stack Overflow用户

发布于 2012-07-06 01:53:37

我希望我能以正确的方式理解你。

forkjoinpool中有一个内部队列,它保存了你想要执行的任务,所以不会抛出堆栈溢出,但你必须为高内存利用率做好准备。

fork方法非常有趣的地方是使用了不安全对象的ForkJoinWorkerThread.pushTask,所以你应该注意数组是用来存储任务的。

EDIT: First and simple --当你在队列的顶端时,你被简单地解压并执行,然后返回retult。(forkjointask.java:353)

当你有依赖关系时,使用不同的方法,在这种情况下,控制返回给WorkerThread,然后他负责检测链并执行它们。first worker检查本地队列中是否有未授权的任务,如果没有未授权的任务,则执行传递的作业并返回结果,否则继续执行下一种情况。这对偷窃者有几次帮助。什么都帮不上忙。重试次数在第一步等于MAX_HELP,现在是零-控制传递给池,池执行几个检查并执行tryAwaitDone。在此方法中,调用wait来等待任务完成。

这意味着fork join池将在几个步骤中完成,试图通过避免调用等待来优化速度和时间。然而,它可能会在等待中完成,那么这将意味着启动同步过程,这是非常昂贵的。

因此,不存在无限深度的后续连接,但逻辑尝试尽可能快地执行任务。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11262474

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档