Java7で導入されたFork/Joinフレームワークの実装について読みましたが、魔法がどのように機能するかを理解していることを確認したかっただけです。
私が理解しているように、スレッドがフォークすると、キューにサブタスクが作成されます(他のスレッドが盗む場合と盗まない場合があります)。スレッドが「参加」しようとすると、実際にキューで既存のタスクをチェックしてから再帰的に実行します。つまり、「参加」操作では、2つのフレームがスレッド呼び出しスタックに追加されます(1つは参加用、もう1つは1つ)。新しく実行されたタスクの呼び出し用)。
JVMは末尾呼び出しの最適化(この状況でjoinメソッドのスタックフレームを削除するのに役立つ可能性があります)をサポートしていないことを知っているので、多くのフォークと結合で複雑な操作を実行すると、スレッドがスローされる可能性があると思いますStackOverflowError
。
私は正しいですか、それとも彼らはそれを防ぐためのいくつかのクールな方法を見つけましたか?
編集
質問を明確にするのに役立つシナリオを次に示します。(簡単にするために)フォークジョインプールにはスレッドが1つしかないことを伝えます。ある時点で、スレッドはフォークしてからjoinを呼び出します。joinメソッドを使用している間、スレッドは(キューで見つかったように)フォークされたタスクを実行できることを検出し、次のタスクを呼び出します。このタスクは次にフォークしてからjoinを呼び出します。そのため、joinメソッドを実行している間、スレッドは(前と同様に)キュー内でフォークされたタスクを見つけて呼び出します。その段階では、コールスタックには少なくとも2つの結合と2つのタスクのフレームが含まれます。
ご覧のとおり、フォーク結合フレームワークは単純な再帰に変換されています。Javaは末尾呼び出しの最適化をサポートしていないため、Javaでのすべての再帰は、StackOverflowError
十分に深くなると発生する可能性があります。
私の質問は-fork/joinフレームワークの実装者は、この状況を防ぐためのクールな方法を見つけましたか?