Java 中的 java.util.concurrent.RecursiveAction 类及其示例

2025年6月19日 | 阅读 6 分钟

RecursiveAction 类仅用于不返回任何结果的任务,它是 java.util.concurrent.ForkJoinTask 的抽象子类。为了表示任务不提供结果,它扩展了 java.lang.Void 类。

RecursiveAction 用于处理可以分解并可以并发执行的任务。例如,RecursiveAction 可以通过将大数组分解成更小、更易于管理的数据块,并在不同核心上分别对它们进行排序,从而轻松地对大数组进行排序。

关键特性和方法

作为 ForkJoinTask 的子类,RecursiveAction 继承了一些有用的方法,如 Fork()、join() 和 call()。这些方法使得工作能够在 Fork/Join 池中执行,从而实现有效的并行执行。

递归执行: RecursiveAction 中的 compute() 方法是需要实现的主要方法。它定义了为特定任务需要执行的计算。此方法可以将任务分解成更小的子任务,使用 fork() 调用它们,然后使用 join() 合并结果。

递归终止: 为了防止无限递归循环,compute() 方法应包含终止条件。此条件检查任务是否已足够小,可以按顺序解决。如果满足终止条件,则任务可以直接执行其计算,而无需进一步递归。

示例

作为 ForkJoinTask 的子类,RecursiveAction 继承了一些有用的方法,如 Fork()、join() 和 call()。这些方法使得工作能够在 Fork/Join 池中执行,从而实现有效的并行执行。

递归执行: RecursiveAction 中的 compute() 方法是需要实现的主要方法。它定义了为特定任务需要执行的计算。此方法可以将任务分解成更小的子任务,使用 fork() 调用它们,然后使用 join() 合并结果。

递归终止: 为了防止无限递归循环,compute() 方法应包含终止条件。此条件检查任务是否已足够小,可以按顺序解决。如果满足终止条件,则任务可以直接执行其计算,而无需进一步递归。

为了说明 RecursiveAction 的用法,我们考虑一个计算整数数组之和的示例。我们可以将数组分解成更小的子数组,并发地计算每个子数组的和,然后合并结果以获得最终的和。

文件名:RecursiveActionClass.java

输出

Sum: 55

在此示例中,SumTask 类覆盖了 compute() 方法,该类继承了 RecursiveAction。如果数组的大小小于或等于阈值,该任务将使用 computeSequentially() 函数按顺序计算总和。否则,它将任务分成两个更小的任务,并递归计算每个任务的总和。为了得到最终的总量,它最后合并了两个子任务的结果。

要使用 SumTask 类,我们可以创建它的一个实例并调用其 invoke() 方法,如下所示:

文件名:RecursiveTaskClass.java

输出

Sum: 55

在此示例中,SumTask 类现在扩展了 RecursiveTask<Integer> 而不是 RecursiveAction。compute() 方法返回一个 Integer 值而不是 void,并且计算逻辑也相应地进行了调整。forkJoinPool.invoke(sumTask) 的结果现在直接分配给 sum 变量。

在 Java 中,RecursiveAction 类是 java.util.concurrent 包的一部分,用于创建不返回结果的递归任务。它通常与 Fork/Join 框架结合使用以实现并行计算。

方法

以下是一些常用的与 RecursiveAction 类一起使用的方法:

protected abstract void compute(): 此方法必须由 RecursiveAction 的子类实现。它代表需要执行的计算。它可以是递归的,其中任务被分解为更小的子任务。

protected void invokeAll(RecursiveAction... actions): 此方法可用于并发调用多个递归操作。它启动指定操作的执行并等待它们完成。

protected abstract void setRawResult(Void value): 此方法用于设置计算的原始结果。由于 RecursiveAction 不返回结果,因此通常不使用 setRawResult() 方法。

protected abstract Void getRawResult(): 此方法检索计算的原始结果。由于 RecursiveAction 不返回结果,因此通常不使用 getRawResult() 方法。

protected boolean computeInParallel(): 此方法是一个钩子,允许子类控制计算是应该分解成更小的子任务并并行执行,还是不执行。默认情况下,它返回 true,表示计算应该并行执行。

protected void setDone(): 此方法将任务标记为已完成。通常在计算完成后调用。

这些是 RecursiveAction 类的一些常用方法。通过扩展此类并实现 compute() 方法,您可以创建可以使用 Fork/Join 框架并行执行的递归任务。

这是一个完整的示例,包括上面提到的 Java 方法的实现:

文件名: MyRecursiveAction.java

输出

Processing: 1
Processing: 2
Processing: 3
Processing: 4
Processing: 5
Processing: 6
Processing: 7
Processing: 8
Processing: 9
Processing: 10

结论

java.util.concurrent 包中的 RecursiveAction 类为实现遵循“分而治之”原则的并行算法提供了一个有用的方法。它简化了将问题分解为更小的子问题并合并其结果的过程。通过利用 RecursiveAction 类和 Fork/Join 框架,开发人员可以利用并行处理能力并提高应用程序的性能。