У меня есть операция ввода / вывода, которая должна быть сделана многопоточной.Это рекурсивный алгоритм, где задача порождает больше подзадач в рекурсии.Я читал, что пул FJ можно использовать для рекурсивных задач, поэтому попробовал 2 вещи, которые используют пул FJ.
1 Параллельные потоки, которые используют общий FJpool по умолчанию -> Я заметил, что в этом случае поток отключен- загрузил свою задачу для запуска своей подзадачи.Допустим, есть рабочий-поток1 из FJCommonPool, и я вижу, что он выгружал свою задачу и запускал все подзадачи в рекурсивном процессе.
2 CompletableFuture.supplyAsync (Some-function, Custom-FJPool) -> Я заметил, что если я отправлю эту задачу в Custom-FJPool, поток не выполнит свою задачу для запуска своей подзадачи, но было замечено, что каждая подзадача была назначена новому потоку из пользовательского пула.Поскольку его рекурсия и после того, как Custom-FJPool вышел из потоков, он пытается компенсировать это путем добавления большего количества потоков, поэтому число активных потоков увеличивается, но ни один из запущенных потоков все еще не равен уровню параллелизма Custom-FJPool или равен ему.Я думал, что даже с Custom-FJPool поток должен был разгрузить свою задачу для выполнения своей подзадачи, но этого не произошло.
Может кто-нибудь поделиться некоторыми соображениями, почему поведение потоков Custom-FJPool отличается от Common-FJPool и почему выгрузка задач не происходит с пользовательским пулом FJ.
Пример
Давайте рассмотрим древовидную структуру, но для простоты предположим, что у каждого родителя есть один дочерний элемент (LinkedList
структура).Так что это может быть что-то вроде ParentDir/d1/d2/d3/d4/d5/d6/d7/d8/d9
.Теперь, если я хочу удалить ParentDir
, алгоритм будет что-то вроде рекурсивного поиска конечного узла и, найдя его, начнёт удаление, пока мы не удалим ParentDir
.Если этот алгоритм генерируется в параллельных потоках, использующих commonForkJoinPool, то видно, что только 1 поток из commonFJPool будет выполнять всю задачу.Он разгружает задачи и начинает работать с подзадачами (удаляя дочерние элементы) и т. Д. До тех пор, пока не будет удалено ParentDir
.
Но если этот же алгоритм выполняется с использованием параллельных потоков с использованием пользовательского FJPool, то его, видимый как поток T1, назначаютзадача удаления ParentDir
, нить T2 для удаления дочерних элементов d1
, нить T3 для дочерних элементов d3
и T4 для d4
и т. д.Так что здесь никакой разгрузки задач не происходит, как это видно с commonFJPool.Мне любопытно, почему это происходит?