JDK7提供了一个将任务“分而治之”的框架 — Fork/Join。它把一个大的任务分割成足够小的子任务,如果子任务比较大的话还要对子任务进行继续分割。分割的子任务分别放到双端队列里,然后启动线程分别从双端队列里获取任务执行。子任务执行完的结果都放在另外一个队列里,启动一个线程从队列里取数据,然后合并这些数据。
Fork/Join的思想如下所示:
RecursiveTask
RecursiveTask适用于将任务分而治之,并且有返回值的情况,举个计算1到100和的例子:
1 | public class RecursiveTest { |
ForkJoinPool使用submit或invoke提交的区别:invoke是同步执行,调用之后需要等待任务完成,才能执行后面的代码;submit是异步执行,只有在Future调用get的时候会阻塞。
启动程序输出如下:
其实这里执行子任务调用fork方法并不是最佳的选择,最佳的选择是invokeAll方法:
1 | // 执行子任务 |
RecursiveAction
使用方式和RecursiveTask类似,只不过没有返回值:
1 | public class RecursiveActionTest { |
输出结果也是5050。
什么时候用
上面只是为了演示Fork/Join的用法,实际是采用这种方式计算反而更加费时,因为切割任务,分配线程需要额外的开销。其实什么时候用不必太纠结,一个足够大的任务,如果采用Fork/Join来处理比传统处理方式快的话,那就毫不犹豫的选择它吧!