Я прочитал о реализации структуры Fork/Join, которая была представлена в Java 7, и я просто хотел проверить, что я понимаю, как работает магия.
Как я понимаю, когда поток вилки, он создает подзадачи в своей очереди (какой другой поток может или не может украсть). Когда поток пытается "присоединиться", он фактически проверяет свою очередь на существующие задачи, а затем рекурсивно выполняет их, что означает, что для любой операции "join" - 2 кадра будут добавлены в стек вызовов потока (один для соединения и один для нового принятого вызова задачи).
Как я знаю, JVM не поддерживает оптимизацию хвостовых вызовов (которая может служить в этой ситуации для удаления фрейма стека метода соединения) Я считаю, что при выполнении сложной операции с большим количеством вилок и объединении потока может StackOverflowError
.
Я прав, или они нашли какой-нибудь классный способ предотвратить это?
EDIT
Вот сценарий, который поможет прояснить вопрос: Скажите (для простоты), что у нас есть только один поток в пуле forkjoin. В какой-то момент времени поток вилки и затем звонки соединяются. В то время как в методе соединения поток обнаруживает, что он может выполнить разветвленную задачу (как она найдена в ее очереди), поэтому она вызывает следующую задачу. Эта задача, в свою очередь, вилки, а затем вызывает join - поэтому при выполнении метода соединения поток найдет разветвленную задачу в своей очереди (как и раньше) и вызовет ее. на этом этапе стек вызовов будет содержать по крайней мере кадры для двух соединений и двух задач.
поскольку вы можете видеть, что каркас fork join преобразован в обычную рекурсию. Поскольку java не поддерживает оптимизацию хвостового вызова - каждая рекурсия в java может вызвать StackOverflowError
, если она будет достаточно глубокой.
Мой вопрос в том, что разработчик инфраструктуры fork/join нашел классный способ предотвратить эту ситуацию.