gpt4 book ai didi

java - ForkJoinPool 和普通 ExecutionService 的区别?

转载 作者:搜寻专家 更新时间:2023-10-31 20:01:38 26 4
gpt4 key购买 nike

我读了一篇关于 fork-join framework in Java 7 的精彩文章,想法是,通过 ForkJoinPoolForkJoinTask,池中的线程可以从其他任务中获取子任务,因此可以使用更少的线程来处理更多任务。

然后我尝试使用普通的 ExecutorService 做同样的工作,发现我无法区分,因为当我向池中提交新任务时,任务将运行在另一个可用线程上。

我能看出的唯一区别是,如果我使用 ForkJoinPool,我不需要将池传递给任务,因为我可以调用 task.fork() 让它在另一个线程上运行。但是对于普通的 ExecutorService,我必须将池传递给任务,或者将其设为静态,因此在任务内部,我可以调用 pool.submit(newTask)

我错过了什么吗?

(可以从https://github.com/freewind/fork-join-test/tree/master/src查看活码)

最佳答案

尽管 ForkJoinPool 实现了 ExecutorService,但它在概念上不同于“普通”执行器。

如果您的任务产生更多任务并等待它们完成,您可以很容易地看到差异,例如通过调用

executor.invoke(new Task()); // blocks this thread until new task completes

在一个普通的执行器服务中,等待其他任务完成会阻塞当前线程。有两种可能的结果:如果您的执行程序服务有一个固定数量的线程,如果最后一个运行的线程等待另一个任务完成,它可能会死锁。如果您的执行程序按需动态创建新线程,线程数量可能会激增,您最终会拥有数千个线程,这可能会导致饥饿。

相反,fork/join框架在执行其他任务的同时重用了线程,所以即使线程数固定,也不会死锁:

new MyForkJoinTask().invoke();

因此,如果您遇到可以递归解决的问题,请考虑使用 ForkJoinPool,因为您可以轻松实现一级递归,如 ForkJoinTask

只需检查示例中正在运行的线程数即可。

关于java - ForkJoinPool 和普通 ExecutionService 的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29988713/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com