目录:
一、 使用到的methods
二、 前提介绍
三、 内容理解
四、 几个重要的点
五、 实例
正文:
一、 本章节主要用到的methods有:fork(), join(), compute()
二、 前提介绍: ThreadPool
-
Thread pool包含了:
(1) threads:相当于执行任务的工人
(2) 排队等着被执行的tasks -
tasks在ThreadPool中是以Queue的形式存在。最先放进Queue的task最后被thread执行(FILO)。 并且,Task queue是两端开口(doubled ending), 头尾都可以取出任务,允许了任务窃取(见下方第4点)的实现。
-
ForkJoinPool是Java中针对Fork-Join模型,对ThreadPool微调后的实现。
-
ForkJoinPool支持任务窃取(work stealing): 当一个Thread空闲时可以从另一个Thread的task queue的尾部窃取任务来执行,以提高执行效率。
三、ForkJoinPool介绍
- fork() 负责把大任务切成小任务;
- join() 负责收集小任务的结果;
- fork()和join()的使用,实现了并行(parallelism),在大部分情况下可以提高运算的效率。
- 至于 compute(), 在该方法内部就把fork()和join()都完成了,属于sequential function。
*(以下图片摘自Introduction to Thread Pool ForkJoinPool, FatalErrors, 来源:https://www.fatalerrors.org/a/0tt10D0.html)*
四、 Take notes - 几个重要的点
- 提问:join()的作用是收集小任务返回的结果,那么 若小任务并没有返回值,可以只fork() 不join()吗?
答案是 不可以。 一旦有fork(), 就要有join(),这样更安全。
考虑一下这种情况: 如下代码,假设该主函数中f1需要15分钟执行完, 但除f1外的其他函数只要1分钟就能执行完, 那么结果会是 主函数在执行完f1.fork() - 即把f1放进任务队列里, 就会直接return退出。至于此时还没结束的f1, 随着主函数的退出也会被直接中断。
因此,若在主函数的最后有 f1.join(), 那么主函数在退出前一定会等待f1执行完。
public static void main(String[] args) {
//...省略一些执行tasks 的代码
f1.fork();
//没有f1.join()
}
- 最先执行fork()的任务,一定要最后进行join() - 这样更有效率