二、Java并发之Fork-Join

}
@Override
protected void compute() {
    if (workload.length() > THRESHOLD) {
        // 任务拆分
        ForkJoinTask.invokeAll(createSubtasks());
    } else {
       // 执行业务逻辑
       processing(workload);
    }
}
private List<CustomRecursiveAction> createSubtasks() {
    List<CustomRecursiveAction> subtasks = new ArrayList<>();
    String partOne = workload.substring(0, workload.length() / 2);
    String partTwo = workload.substring(workload.length() / 2, workload.length());
    subtasks.add(new CustomRecursiveAction(partOne));
    subtasks.add(new CustomRecursiveAction(partTwo));
    return subtasks;
}
private void processing(String work) {
    String result = work.toUpperCase();
    logger.info("This result - (" + result + ") - was processed by "
      + Thread.currentThread().getName());
}

在这个示例中,我们使用了一个字符串类型 ( String ) 的名为 workload 属性来表示要处理的工作单元。同时,为了演示 Fork/Join 框架的 fork 行为,在该示例中,如果 workload.length() 大于指定的阈值,那么就使用 createSubtask() 方法拆分任务。  
 在createSubtasks() 方法中,输入的字符串被递归地划分为子串,然后创建基于这些子串的 CustomRecursiveTask 实例。


当递归分割字符串完毕时,createSubtasks() 方法返回 List 作为结果。然后在compute() 方法中使用 invokeAll() 方法将任务列表提交给 ForkJoinPool 线程池。


##### RecursiveTask 使用示例


对于有返回值的任务,除了将每个子任务的结果在一个结果中合并,其它逻辑和 RecursiveAction 都差不多。



public class CustomRecursiveTask extends RecursiveTask {
private int[] arr;
private static final int THRESHOLD = 20;
public CustomRecursiveTask(int[] arr) {
this.arr = arr;
}
@Override
protected Integer compute() {
if (arr.length > THRESHOLD) {
// 任务拆分
return ForkJoinTask.invokeAll(createSubtasks())
.stream()
.mapToInt(ForkJoinTask::join)
.sum();
} else {
// 执行业务逻辑
return processing(arr);
}
}
private Collection createSubtasks() {
List dividedTasks = new ArrayList<>();
dividedTasks.add(new CustomRecursiveTask(
Arrays.copyOfRange(arr, 0, arr.length / 2)));
dividedTasks.add(new CustomRecursiveTask(
Arrays.copyOfRange(arr, arr.length / 2, arr.length)));
return dividedTasks;
}
private Integer processing(int[] arr) {
return Arrays.stream(arr)
.filter(a -> a > 10 && a < 27)
.map(a -> a * 10)
.sum();
}


在上面这个示例中,任务由存储在 CustomRecursiveTask 类的 arr 字段中的数组表示。createSubtask() 方法递归地将任务划分为较小的工作,直到每个部分小于阈值。  
 然后,invokeAll()方法将子任务提交给公共拉取并返回 Future 列表。  
 要触发执行,需要为每个子任务调用 join() 方法。


上面这个示例中,我们使用了 Java 8 的流 ( Stream ) API , sum() 方法用于将子结果组合到最终结果中。


##### 将任务提交到 ForkJoinPool 线程池中


只要使用很少的方法,就可以把任务提交到 ForkJoinPool 线程池中。


###### submit()或execute()方法


这两个方法的调用方式是相同的



forkJoinPool.execute(customRecursiveTask);
int result = customRecursiveTask.join();


###### 使用invoke()方法fork任务并等待结果,不需要任何手动连接(join)



int result = forkJoinPool.invoke(customRecursiveTask);


###### invokeAll()方法


将ForkJoinTasks序列提交给ForkJoinPool的最方便的方法它将任务作为参数(两个任务,varargs或集合),fork它们,并按照生成它们的顺序返回Future对象的集合。


###### 使用单独的fork()和join()方法


fork() 方法将任务提交给线程池,但不会触发任务的执行;join() 方法则用于触发任务的执行。在 RecursiveAction 的情况下,join() 返回 null,但对于 RecursiveTask ,它返回任务执行的结果。



customRecursiveTaskFirst.fork();
result = customRecursiveTaskLast.join();


上面的RecursiveTask 示例中,我们使用 invokeAll() 方法向线程池提交一系列子任务。同样的工作,也可以使用 fork() 和 join() 来完成,但这可能会对结果的排序产生影响。  
 为了避免混淆,当涉及到多个任务且要保证任务的顺序时,通常都是使用 ForkJoinPool.invokeAll()。


### 最后

看完上述知识点如果你深感Java基础不够扎实,或者刷题刷的不够、知识不全面

小编专门为你量身定制了一套<Java一线大厂高岗面试题解析合集:JAVA基础-中级-高级面试+SSM框架+分布式+性能调优+微服务+并发编程+网络+设计模式+数据结构与算法>

![image](https://img-blog.csdnimg.cn/img_convert/c3c7728db7d8945711c967cc66db8706.webp?x-oss-process=image/format,png)

针对知识面不够,也莫慌!还有一整套的<Java核心进阶手册>,可以瞬间查漏补缺

![image](https://img-blog.csdnimg.cn/img_convert/c0ec97508e4f888cf87bc2f5e85ea869.webp?x-oss-process=image/format,png)

> 全都是一丢一丢的收集整理纯手打出来的


更有纯手绘的各大知识体系大纲,可供梳理:Java筑基、MySQL、Redis、并发编程、Spring、分布式高性能架构知识、微服务架构知识、开源框架知识点等等的xmind手绘图~

![image](https://img-blog.csdnimg.cn/img_convert/74a78b0050974b84d067c420fab6a2c4.webp?x-oss-process=image/format,png)

![image](https://img-blog.csdnimg.cn/img_convert/25737890ec9f8c0d66315f83a9637bcf.webp?x-oss-process=image/format,png)

Java筑基、MySQL、Redis、并发编程、Spring、分布式高性能架构知识、微服务架构知识、开源框架知识点等等的xmind手绘图~

[外链图片转存中...(img-3UeGb3nn-1714557759684)]

[外链图片转存中...(img-UcYEt5zy-1714557759685)]

> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/topics/618154847)收录**
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值