我有一个I / O操作,该操作将成为多线程的。它是一种递归算法,其中任务以递归方式生成更多子任务。我读到FJ池可用于递归任务,因此尝试了两种使用FJ池的方法。
1使用默认公共FJpool的并行流->我观察到,在这种情况下,线程将其任务卸载以运行其子任务。因此,可以说有一个来自FJCommonPool的worker-thread1,我看到它卸载了任务,并以递归过程运行了所有子任务。
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的并行流,则可以看到commonFJPool中只有1个线程可以完成整个任务。它会卸载任务并开始处理子任务(删除子任务),依此类推,直到删除ParentDir
。
但是,如果使用自定义FJPool使用并行流执行相同的算法,则将被视为线程T1的任务分配为删除ParentDir
,将线程T2分配为删除子节点d1
,将线程T3分配给子进程{ {1}}和T4到d3
,依此类推。因此,与commonFJPool一样,这里没有发生任务的卸载。我很好奇为什么会这样?