当前位置:网站首页>【JUC系列】Fork/Join框架之概览
【JUC系列】Fork/Join框架之概览
2022-06-30 07:58:00 【顧棟】
JUC系列Fork/Join框架
Fork/Join框架是Java并发工具包中的一种可以将一个大任务拆分为很多小任务来异步执行的工具,自JDK1.7引入。
Fork/Join总览类图

主要模块
ForkJoinPool可以通过池中的ForkJoinWorkerThread来处理ForkJoinTask任务。
ForkJoinPool只接收ForkJoinTask任务(在实际使用中,也可以接收Runnable/Callable任务,但在真正运行时,也会把这些任务封装成ForkJoinTask类型的任务),RecursiveTask是ForkJoinTask的子类,是一个可以递归执行的ForkJoinTask,RecursiveAction是一个无返回值的RecursiveTask,CountedCompleter 在任务完成执行后会触发执行一个自定义的钩子函数。
在实际运用中,我们一般都会继承 RecursiveTask 、RecursiveAction 或 CountedCompleter 来实现我们的业务需求,而不会直接继承ForkJoinTask类。
核心类
任务对象:
ForkJoinTask
任务管理的线程池
ForkJoinPool
执行任务的线程
ForkJoinWorkerThread
核心算法:分治算法
核心算法:工作窃取法
work-stealing(工作窃取)算法: 线程池内的所有工作线程都尝试找到并执行已经提交的任务,或者是被其他活动任务创建的子任务(如果不存在就阻塞等待)。这种特性使得 ForkJoinPool 在运行多个可以产生子任务的任务,或者是提交的许多小任务时效率更高。尤其是构建异步模型的 ForkJoinPool 时,对不需要合并(join)的事件类型任务也非常适用。
在 ForkJoinPool 中,线程池中每个工作线程(ForkJoinWorkerThread)都对应一个任务队列(WorkQueue),工作线程优先处理来自自身队列的任务(LIFO或FIFO顺序,参数 mode 决定),然后以FIFO的顺序随机窃取其他队列中的任务。
使用示例
RecursiveAction使用
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
public class SortTask extends RecursiveAction {
final long[] array;
final int low;
final int high;
private int THRESHOLD = 0;
public SortTask(long[] array) {
this.array = array;
this.low = 0;
this.high = array.length - 1;
}
public SortTask(long[] array, int low, int high) {
this.array = array;
this.low = low;
this.high = high;
}
@Override
protected void compute() {
System.out.println("[" + new SimpleDateFormat("HH:mm:ss.SSS").format(new Date()) + "--" + Thread.currentThread().getName() + "] task is [low=" + low + ", high=" + high + "].");
if (low < high) {
int pivot = partition(array, low, high);
SortTask left = new SortTask(array, low, pivot - 1);
SortTask right = new SortTask(array, pivot + 1, high);
left.fork();
right.fork();
left.join();
right.join();
}
}
private int partition(long[] array, int low, int high) {
long x = array[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (array[j] <= x) {
i++;
swap(array, i, j);
}
}
swap(array, i + 1, high);
return i + 1;
}
private void swap(long[] array, int i, int j) {
if (i != j) {
long temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
public static void main(String[] args) throws Exception {
long[] array = {
10, 0, 21, 44, 52, 30};
SortTask sort = new SortTask(array);
ForkJoinPool pool = new ForkJoinPool();
pool.submit(sort);
boolean flag = true;
while (flag) {
if (sort.isDone()) {
StringBuilder a = new StringBuilder();
for (int i = 0; i < sort.array.length; i++) {
a.append(sort.array[i]).append(" ");
}
System.out.println("[" + new SimpleDateFormat("HH:mm:ss.SSS").format(new Date()) + "--" + Thread.currentThread().getName() + "] a is [" + a.substring(0, a.length() - 1) + "].");
flag = false;
}
}
pool.shutdown();
}
}
执行结果
[18:06:06.143--ForkJoinPool-1-worker-1] task is [low=0, high=5].
[18:06:06.143--ForkJoinPool-1-worker-2] task is [low=0, high=2].
[18:06:06.143--ForkJoinPool-1-worker-2] task is [low=0, high=1].
[18:06:06.143--ForkJoinPool-1-worker-2] task is [low=0, high=-1].
[18:06:06.143--ForkJoinPool-1-worker-2] task is [low=1, high=1].
[18:06:06.143--ForkJoinPool-1-worker-2] task is [low=3, high=2].
[18:06:06.159--ForkJoinPool-1-worker-2] task is [low=4, high=5].
[18:06:06.159--ForkJoinPool-1-worker-2] task is [low=4, high=3].
[18:06:06.159--ForkJoinPool-1-worker-2] task is [low=5, high=5].
[18:06:06.159--main] a is [0 10 21 30 44 52].
RecursiveTask使用
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;
public class SumTask extends RecursiveTask<Long> {
private static final int THRESHOLD = 10;
private long start;
private long end;
public SumTask(long end) {
this(0, end);
}
private SumTask(long start, long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
long sum = 0;
if ((end - start) <= THRESHOLD) {
System.out.println("[" + new SimpleDateFormat("HH:mm:ss.SSS").format(new Date()) + "--" + Thread.currentThread().getName() + "] task is [" + start + "," + end + "].");
for (long l = start; l <= end; l++) {
sum += l;
}
} else {
long mid = (start + end) >>> 1;
SumTask left = new SumTask(start, mid);
SumTask right = new SumTask(mid + 1, end);
left.fork();
right.fork();
sum = left.join() + right.join();
}
return sum;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
SumTask sumTask = new SumTask(100);
ForkJoinPool pool = new ForkJoinPool();
Future<Long> future = pool.submit(sumTask);
boolean flag = true;
while (flag) {
if (future.isDone()) {
System.out.println("[" + new SimpleDateFormat("HH:mm:ss.SSS").format(new Date()) + "--" + Thread.currentThread().getName() + "] sum = [" + future.get() + "].");
flag = false;
}
}
pool.shutdown();
}
}
执行结果
[18:09:09.123--ForkJoinPool-1-worker-2] task is [26,32].
[18:09:09.123--ForkJoinPool-1-worker-0] task is [39,44].
[18:09:09.123--ForkJoinPool-1-worker-3] task is [51,57].
[18:09:09.123--ForkJoinPool-1-worker-2] task is [33,38].
[18:09:09.123--ForkJoinPool-1-worker-1] task is [0,6].
[18:09:09.123--ForkJoinPool-1-worker-3] task is [58,63].
[18:09:09.123--ForkJoinPool-1-worker-0] task is [45,50].
[18:09:09.123--ForkJoinPool-1-worker-3] task is [64,69].
[18:09:09.123--ForkJoinPool-1-worker-0] task is [76,82].
[18:09:09.123--ForkJoinPool-1-worker-3] task is [70,75].
[18:09:09.123--ForkJoinPool-1-worker-0] task is [83,88].
[18:09:09.123--ForkJoinPool-1-worker-3] task is [89,94].
[18:09:09.123--ForkJoinPool-1-worker-0] task is [95,100].
[18:09:09.123--ForkJoinPool-1-worker-3] task is [13,19].
[18:09:09.123--ForkJoinPool-1-worker-2] task is [20,25].
[18:09:09.123--ForkJoinPool-1-worker-2] task is [7,12].
[18:09:09.123--main] sum = [5050].
参考链接:https://www.pdai.tech/md/java/thread/java-thread-x-juc-executor-ForkJoinPool.html
边栏推荐
- right four steps of SEIF SLAM
- Self study notes -- use of 74h573
- 【Tensorflow-gpu】window11下深度学习环境搭建
- How CRM & PM helps enterprises create optimal sales performance
- Palindrome substring, palindrome subsequence
- 深度学习——LSTM
- 你了解IP协议吗?
- Use of nested loops and output instances
- Final review -php learning notes 2-php language foundation
- 深度学习——BRNN和DRNN
猜你喜欢

深度学习——序列模型and数学符号

【花雕体验】14 行空板pinpong库测试外接传感器模块(之一)

Network security and data in 2021: collection of new compliance review articles (215 pages)

Efga design open source framework openlane series (I) development environment construction

What management improvements can CRM bring to enterprises

Bingbing learning notes: quick sorting

1162 Postfix Expression

Examen final - notes d'apprentissage PHP 3 - Déclaration de contrôle du processus PHP

25岁,从天坑行业提桶跑路,在经历千辛万苦转行程序员,属于我的春天终于来了

6月底了,可以开始做准备了,不然这么赚钱的行业就没你的份了
随机推荐
JS代码案例
Want to change careers, but don't know what to do? This article is written for you who are confused
Efga design open source framework openlane series (I) development environment construction
深度学习——卷积的滑动窗口实现
String and underlying character types of go data type
JS code case
Basic theory of four elements and its application
AcrelEMS能效管理平台为高层小区用电安全保驾护航
【花雕体验】12 搭建ESP32C3之Arduino开发环境
【Tensorflow-gpu】window11下深度学习环境搭建
November 21, 2021 [reading notes] - bioinformatics and functional genomics (Chapter 5 advanced database search)
MySQL cannot connect to the intranet database
Introduction notes to pytorch deep learning (10) neural network convolution layer
Recurrence relation (difference equation) -- Hanoi problem
Program acceleration
期末复习-PHP学习笔记5-PHP数组
Development technology sharing of Jingtan NFT digital collection system
Multi whale capital: report on China's education intelligent hardware industry in 2022
December 13, 2021 [reading notes] | understanding of chain specific database building
期末复习-PHP学习笔记2-PHP语言基础