我读到了 Java 7 中引入的 Fork/Join 框架的实现,我只是想检查一下我是否理解这个魔法是如何工作的。
据我了解,当一个线程分叉时,它会在其队列中创建子任务(其他线程可能会或可能不会窃取)。当线程尝试“加入”时,它实际上会检查其队列中的现有任务,然后递归地执行它们,这意味着对于任何“加入”操作 - 2 帧将被添加到线程调用堆栈中(一个用于加入,一个用于对于新的任务调用)。
据我所知,JVM 不支持尾调用优化(在这种情况下可能用于删除 join 方法堆栈帧),我相信在执行具有大量分叉和连接的复杂操作时,线程可能会抛出StackOverflowError
.
我是对的还是他们找到了一些很酷的方法来防止它?
编辑
这是一个有助于澄清问题的场景:假设(为简单起见)我们在 forkjoin 池中只有一个线程。在某个时间点 - 线程分叉,然后调用 join。在 join 方法中,线程发现它可以执行分叉的任务(正如它在其队列中发现的那样),因此它调用下一个任务。该任务依次分叉,然后调用 join - 因此在执行 join 方法时,线程将在其队列中找到分叉的任务(如前所述)并调用它。在那个阶段,调用堆栈将至少包含两个连接和两个任务的帧。
如您所见,fork join 框架已转换为普通递归。因为 java 不支持尾调用优化 - java 中的每个递归都可能导致StackOverflowError
如果它足够深。
我的问题是——fork/join 框架的实现者是否找到了一些很酷的方法来防止这种情况。