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