ForkJoinPool
总结
一个特殊线程池,它专门用于执行 ForkJoinTask;
设计目的是为了更有效地处理 可以被分解成更小任务 的工作负载,这些任务可以通过递归地分叉(fork)和合并(join)来并行执行。
这种模式非常适合于分治算法,比如快速排序、矩阵乘法等。
特性
- 工作窃取:
ForkJoinPool
使用了一种称为“工作窃取”的算法,其中 空闲的线程 可以 从其他忙于处理任务的线程 那里“窃取”待处理的任务。这有助于保持所有线程忙碌,从而提高整体效率。 - 轻量级子任务:
ForkJoinTask
通常代表一个轻量级的子任务,这样可以减少任务切换的开销。 - 动态调整:
ForkJoinPool
可以根据需要动态调整其大小,但通常建议使用默认设置或显式指定大小。
创建 ForkJoinPool
- 默认构造函数会创建一个与系统可用处理器数量相匹配的线程数的池。
- 也可以通过传递自定义参数来创建
ForkJoinPool
,例如指定线程数、异常处理器等。
ForkJoinTask
ForkJoinTask
是 ForkJoinPool
中执行任务的抽象类,有两个主要的实现:
RecursiveAction
:用于 没有返回结果 的任务。RecursiveTask<V>
:用于 有返回结果 的任务,这里的V
表示返回值类型。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | public class SumCalculator extends RecursiveTask<Long> { private final long [] numbers; private final int start; private final int end; private static final int THRESHOLD = 1000; // 阈值,决定何时停止拆分子任务 public SumCalculator( long [] numbers, int start, int end) { this .numbers = numbers; this .start = start; this .end = end; } @Override protected Long compute() { if (end - start <= THRESHOLD) { // 如果任务足够小,则直接计算 long sum = 0; for ( int i = start; i < end; i++) { sum += numbers[i]; } return sum; } else { // 否则将任务拆分成两个更小的任务 int middle = (start + end) / 2; SumCalculator leftTask = new SumCalculator(numbers, start, middle); SumCalculator rightTask = new SumCalculator(numbers, middle, end); // 异步执行左边的任务 leftTask.fork(); // 计算右边的任务 long rightResult = rightTask.compute(); // 获取左边任务的结果 long leftResult = leftTask. join (); // 返回左右两边任务的结果之和 return leftResult + rightResult; } } public static void main(String[] args) { long [] numbers = new long [100000000]; for ( int i = 0; i < numbers.length; i++) { numbers[i] = i; } ForkJoinPool pool = new ForkJoinPool(); SumCalculator task = new SumCalculator(numbers, 0, numbers.length); long start = System.currentTimeMillis(); long result = pool.invoke(task); // 提交任务并等待完成 System. out .println( "The sum is: " + result + " cost:" + (System.currentTimeMillis() - start)); long start1 = System.currentTimeMillis(); long sum = 0; for ( int i = 0; i < numbers.length; i++) { sum += numbers[i]; } System. out .println( "sum: " + sum + " cost: " + (System.currentTimeMillis() - start1)); } } |
分类:
JavaSE---线程池
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
2019-09-20 《计算机组成原理》---运算方法与运算器
2019-09-20 《计算机组成原理》---计算机中数据信息的表示
2019-09-20 《计算机组成原理》---概论