通常,实现一个简单的并发Java应用程序时,您实现某些 Runnable 对象和对应的 Thread 对象。 您在程序中控制线程的创建、执行及状态。 Java 5对此有改进,提供了 Executor 和 ExecutorService 接口及实现这些接口的类(如 ThreadPoolExecutor 类)
Executor 框架分离了任务的创建和执行。只需要实现 Runnable 对象并使用一个 Executor 对象。 将 Runnable 任务提交给 executor,executor 将创建、管理并结束必要的线程来执行那些任务。
Java 7更进一步,另外包含了面向一个特定类型问题的 ExecutorService 的一个实现。就是 Fork/Join 框架。
此框架设计是为了解决那些可以被分治技术分解为小任务的问题。 在一个任务内,您检查要解决的问题的规模,如果大于一个确定的大小,您将其分解为用此框架执行的更小的任务。 如果问题规模小过确定的大小,您在任务里直接解决,然后框架返回或不返回一个结果。
Task 1 |-分解 -> Task 1.1 | |-分解 -> Task 1.1.1 | |-分解 -> Task 1.1.2 |-分解 -> Task 1.2 |-分解 ->Task 1.2.1 |-分解 ->Task 1.2.2
决定任务是否要被分解的参考规模是没有公式来计算的。您可以使用任务中要处理的元素数目和预计的执行时间来决定参考规模。 试验不同的参考规模来选择对问题最合适的大小。可将 ForkJoinPool 看作一种特殊的 Executor。
此框架基于以下2个操作:
Fork/Join 和 Executor 框架之间的主要区别在于 工作窃取(work-stealing) 算法。 当一个任务在用join操作等待它创建的子任务结束时,在执行该任务的线程(工作线程)查找还没有执行的其他任务并开始执行。 通过这种方式,线程充分利用了运行时间,因此提高了应用程序的性能。
为达到此目的,Fork/Join 框架执行的任务有以下限制:
For/Join 框架的核心由以下2个类组成: