当前位置:网站首页>并发编程系列之什么是ForkJoin框架?
并发编程系列之什么是ForkJoin框架?
2022-07-01 15:40:00 【51CTO】
并发编程系列之什么是ForkJoin框架?
1、什么是ForkJoin框架
ForkJoin框架是java的JUC包里提供的,用于处理一些比较繁重的任务,会将这个大任务分为多个小任务,多个小任务处理完成后会将结果汇总给Result,体现的是一种“分而治之”的思想。第一步,拆分fork任务,将大任务分为多个小任务;第二步,归并join,会将小任务的处理结果进行归并为一个结果。

在这里插入图片描述
2、ForkJoinTask
ForkJoinTask是ForkJoin框架的提供的任务API,ForkJoinTask是一个抽象类,有两个主要的实现类,RecursiveTask和RecursiveAction,其中RecursiveTask和RecursiveAction的主要区别是,RecursiveAction没有返回值,而RecursiveTask是有返回值的

在这里插入图片描述
3、ForkJoinPool
ForkJoinPool类是forkjoin框架的线程池实现,基于ExecutorService接口。这个线程池是jdk1.7才加入的,用于管理线程,执行forkjoin的任务。对于线程池的使用,我们使用ThreadPoolExecutor比较多,可以在idea里看一下uml类图,可以看出ForkJoinPool和ThreadPoolExecutor实现差不多的。

在这里插入图片描述
几个重要的参数:
- parallelism:并行度,并行执行线程,可用指定,也可以不指定,不指定的情况,是根据cpu核数创建可用的线程
- ForkJoinWorkerThreadFactory:创建线程的工厂实现
- UncaughtExceptionHandler :因为未知异常中断的回调处理
- asyncMode:是否异步,默认情况是false
使用时候,可以直接创建ForkJoinPool,可以不传参,不传参的情况,默认指定的线程并行数为Runtime.getRunTime().availableProcessors();,表示根据cpu核数创建可用线程数
也是可用传参,对并行度进行指定的public ForkJoinPool(int parallelism), parallelism并行度,并行执行几个线程
将forkjoin任务加入到FrokJoinPool线程池有几种方式
- execute():调用其 fork 方法在多个线程之间拆分工作。
- invoke():在ForkJoinPool线程池上调用invoke方法
- submit():返回一个Future对象,Future可以进行监控,任务完成后返回结果
4、打印斐波那契数列
ForkJoin框架可以用于一些递归遍历的场景,对于斐波那契数列,你可以比较熟悉,因为在面试中有时候经常问到,斐波那契数列的特点就是最后一项的结果等于前面两项的和
package com.example.concurrent.forkjoin;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
/**
* <pre>
* 斐波那契数列
* </pre>
* <p>
* <pre>
* @author nicky.ma
* 修改记录
* 修改后版本: 修改人: 修改日期: 2021/10/12 16:22 修改内容:
* </pre>
*/
public class Fibonacci extends RecursiveTask<Integer>{
private int n;
public Fibonacci(int n) {
this.n = n;
}
@Override
protected Integer compute() {
if (n <= 1)
return n;
Fibonacci f1 = new Fibonacci(n - 1);
f1.fork();
Fibonacci f2 = new Fibonacci(n - 2);
f2.fork();
return f1.join() + f2.join();
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ForkJoinPool pool = new ForkJoinPool();
for (int i = 0; i< 10; i++) {
ForkJoinTask task = pool.submit(new Fibonacci(i));
System.out.println(task.get());
}
}
}
- 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.
5、ForkJoin归并排序
面试题:快速实现对一个长度百万的数组的排序
难点:可以使用归并排序,多线程如何组织实现归并排序
package com.example.concurrent.forkjoin;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
/**
* <pre>
* 大数组排序
* </pre>
* <p>
* <pre>
* @author mazq
* 修改记录
* 修改后版本: 修改人: 修改日期: 2021/10/12 17:04 修改内容:
* </pre>
*/
public class ArraySortTask extends RecursiveAction{
final long[] array; final int lo, hi;
ArraySortTask(long[] array, int lo, int hi) {
this.array = array; this.lo = lo; this.hi = hi;
}
ArraySortTask(long[] array) { this(array, 0, array.length); }
@Override
protected void compute() {
if (hi - lo < THRESHOLD)
// 少于阀值,使用Arrays.sort 快排
sortSequentially(lo, hi);
else {
/* 归并排序 */
// 取中间值
int mid = (lo + hi) >>> 1;
// 拆分任务
invokeAll(new ArraySortTask(array, lo, mid),
new ArraySortTask(array, mid, hi));
// 归并结果
merge(lo, mid, hi);
}
}
// implementation details follow:
static final int THRESHOLD = 1000;
void sortSequentially(int lo, int hi) {
Arrays.sort(array, lo, hi);
}
void merge(int lo, int mid, int hi) {
long[] buf = Arrays.copyOfRange(array, lo, mid);
for (int i = 0, j = lo, k = mid; i < buf.length; j++)
array[j] = (k == hi || buf[i] < array[k]) ?
buf[i++] : array[k++];
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
int size = 10_000;
long[] array = new long[size];
Random random = new Random();
for (int i = 0; i< size; i++) {
array[i] = random.nextInt();
}
ForkJoinPool forkJoinPool = new ForkJoinPool();
ArraySortTask task = new ArraySortTask(array , 0 , size);
forkJoinPool.submit(task);
task.get();
for (long a : array) {
System.out.println(a);
}
}
}
- 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.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
参考资料
边栏推荐
- MySQL审计插件介绍
- 你TM到底几点下班?!!!
- 【一天学awk】条件与循环
- Zhang Chi Consulting: household appliance enterprises use Six Sigma projects to reduce customers' unreasonable return cases
- The difference between arrow function and ordinary function in JS
- Stm32f4-tft-spi timing logic analyzer commissioning record
- Deep operator overloading (2)
- Can I choose to open an account on Great Wall Securities? Is it safe?
- Tableapi & SQL and Kafka message insertion in Flink
- Introduction to MySQL audit plug-in
猜你喜欢

Intelligent operation and maintenance practice: banking business process and single transaction tracking

Implementation of wechat web page subscription message
![[target tracking] | template update time context information (updatenet)](/img/53/0a8b2135fa4903f30e4573256c393a.png)
[target tracking] | template update time context information (updatenet) "learning the model update for Siamese trackers"

Survey of intrusion detection systems:techniques, datasets and challenges

三星率先投产3nm芯片,上海应届硕士生可直接落户,南开成立芯片科学中心,今日更多大新闻在此...

Stm32f4-tft-spi timing logic analyzer commissioning record

点云重建方法汇总一(PCL-CGAL)

张驰课堂:六西格玛数据的几种类型与区别

MySQL service is starting. MySQL service cannot be started. Solution

STM32ADC模拟/数字转换详解
随机推荐
Rhcsa fourth day operation
Tiantou village, Guankou Town, Xiamen special agricultural products Tiantou Village special agricultural products ant new village 7.1 answer
Returning to the top of the list, the ID is still weak
Zhang Chi's class: several types and differences of Six Sigma data
STM32ADC模拟/数字转换详解
关于用 ABAP 代码手动触发 SAP CRM organization Model 自动决定的研究
MySQL service is starting. MySQL service cannot be started. Solution
点云重建方法汇总一(PCL-CGAL)
Go zero actual combat demo (I)
GaussDB(for MySQL) :Partial Result Cache,通过缓存中间结果对算子进行加速
TensorFlow团队:我们没被抛弃
ABAP-调用Restful API
Tableapi & SQL and Kafka message insertion in Flink
微服务追踪SQL(支持Isto管控下的gorm查询追踪)
Survey of intrusion detection systems:techniques, datasets and challenges
SAP S/4HANA: 一条代码线,许多种选择
Recommendation of data acquisition tools and detailed graphic process of data acquisition list
《性能之巅第2版》阅读笔记(五)--file-system监测
k8s部署redis哨兵的实现
"Qt+pcl Chapter 6" point cloud registration ICP Series 6