JAVA 多线程之ForkJoin

复制代码
Fork/Join 框架是jdk7提供的一个用于并行执行任务的框架,是一个把大任务分成若干小任务,最终汇总每个小任务结果,最终得到大任务计算结果的框架。

        Fork:就是把一个大任务切分成若干小任务,并行执行;
        Join:就是合并这些小任务的执行结果,最终得到大任务的结果。

Fork/Join 根据工作窃取算法进行设计

工作窃取算法:
(work-stealing),是指某个线程从其他队列里窃取任务来执行。

为什么需要工作窃取算法?
  假如有些线程一起工作,可能有些线程的工作早早结束,结束的线程与其等着,不如去帮其他线程干活,于是就去其他线程的队列里,窃取一个任务来执行。
  而在这时,他们会访问同一队列,所以为了减少窃取任务线程和被窃取任务线程之间的竞争,通常会使用双端队列维护;
  被窃取任务的线程永远从双端队列头部拿取任务执行;
  窃取任务线程永远从双端队列尾部拿取任务执行;

Fork/Join 框架设计:
        Fork:分割任务。首先,我们需要一个fork类,来把大任务拆分成子任务,有可能子任务还很大,需要不停的分割,直到分割出子任务足够小。
        抽象类ForkJoinTask提供了两个子抽象类
                RecursiveAction:没有返回结果的任务
                RecursiveTask:有返回结果的任务

        Join:执行任务并合并结果。分割的子任务分别放在双端队列里,然后几个启动线程分别从双端队列里获取线程并执行。子任务执行完的结果同一放到一个队列里,启动一个线程从队列里拿数据
 然后合并这些数据

ForkJoinPool :ForkJoinTask需要通过ForkJoinPool来执行

使用场景:
        可以采用分而治之的算法场景
        计算密集型的任务

示例:
计算 1+2+3+……+100,如果加数之间差值大于等于10,则拆分为子任务。
java 复制代码
package org.test.mem.thread.pool.forkjoin;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

/**
 * Fork/Join 框架是jdk7提供的一个用于并行执行任务的框架,是一个把大任务分成若干小任务,最终汇总每个小任务结果,最终得到大任务计算结果的框架。
 * <p>
 * Fork:就是把一个大任务切分成若干小任务,并行执行;
 * Join:就是合并这些小任务的执行结果,最终得到大任务的结果。
 * <p>
 * Fork/Join 根据工作窃取算法进行设计
 * <p>
 * 工作窃取算法:(work-stealing),是指某个线程从其他队列里窃取任务来执行。
 *
 * 为什么需要工作窃取算法?
 * 假如有些线程一起工作,可能有些线程的工作早早结束,结束的线程与其等着,不如去帮其他线程干活,于是就去其他线程的队列里,窃取一个任务来执行。
 * 而在这时,他们会访问同一队列,所以为了减少窃取任务线程和被窃取任务线程之间的竞争,通常会使用双端队列维护;
 * 被窃取任务的线程永远从双端队列头部拿取任务执行;
 * 窃取任务线程永远从双端队列尾部拿取任务执行;
 *
 * Fork/Join 框架设计:
 * Fork:分割任务。首先,我们需要一个fork类,来把大任务拆分成子任务,有可能子任务还很大,需要不停的分割,直到分割出子任务足够小。
 *   抽象类ForkJoinTask提供了两个子抽象类
 *      RecursiveAction:没有返回结果的任务
 *      RecursiveTask:有返回结果的任务
 *
 * Join:执行任务并合并结果。分割的子任务分别放在双端队列里,然后几个启动线程分别从双端队列里获取线程并执行。子任务执行完的结果同一放到一个队列里,启动一个线程从队列里拿数据
 * 然后合并这些数据
 *
 *  ForkJoinPool :ForkJoinTask需要通过ForkJoinPool来执行
 *
 *
 * 使用场景:
 * 可以采用分而治之的算法场景
 * 计算密集型的任务
 *
 * 实例:
 * 计算 1+2+3+......+100,如果加数之间差值大于等于10,则拆分为子任务。
 *
 * */
public class ForkJoinTest extends RecursiveTask<Integer> {

    private static final int THRESHOLD = 10;
    private int start;
    private int end;

    public ForkJoinTest(int start, int end) {
        this.start = start;
        this.end = end;
    }


    public static void main(String[] args) {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        //计算任务
        ForkJoinTest task = new ForkJoinTest(1, 100);
        //异步执行任务
        ForkJoinTask<Integer> result = forkJoinPool.submit(task);

        try {
            System.out.println(result.get());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }


    }

    @Override
    protected Integer compute() {
        int sum = 0;
        if (end - start < THRESHOLD) {
            for (int i = start; i <= end; i++) {
                sum += i;
//                System.out.println(Thread.currentThread().getName() + ":" + i + " sum:" + sum);
            }
            System.out.println(Thread.currentThread().getName() +" sum:" +sum +" start:"+start+" end:"+end);
            return sum;
        }else{
            int middle = (end + start) / 2;
            ForkJoinTest leftForkJoin = new ForkJoinTest(start, middle);
            ForkJoinTest rightForkJoin = new ForkJoinTest(middle + 1, end);
            leftForkJoin.fork();
            rightForkJoin.fork();
            int leftResult = leftForkJoin.join();
            int rightResult = rightForkJoin.join();
            sum = leftResult + rightResult;
            return sum;
        }
    }
}
相关推荐
大草原的小灰灰6 小时前
Python基础语法
开发语言·python
liangsheng_g6 小时前
SpringAOP拦截器链递归与事务钩子补偿源码实战
java·spring
SL_staff7 小时前
制造业私有化文档平台的技术实践:从知识孤岛到可追溯知识资产
java·spring·开源
小哈里7 小时前
【知识】从学科到实践:自然・工程・社科・人文|算法・研发・产品・品牌设计
程序人生·算法·产品·设计·工程
小π军7 小时前
最大重叠区间数量
数据结构·算法
镜像视界(浙江)科技有限公司8 小时前
《视频孪生之上:二维展示终结,三维空间计算重构城市逻辑》——跨摄像连续表达 × 三角测量厘米级定位 × 动态轨迹建模,构建新一代城市空间
大数据·人工智能·算法·矩阵·音视频·空间计算
泡泡鱼(敲代码中)8 小时前
MySQL基础学习笔记:从数据模型到DDL全掌握
开发语言·数据库·笔记·学习·mysql
SL_staff8 小时前
3天上线OKR系统:一名HR与1名工程师如何用JVS完成全栈交付
java·低代码·开源
a187927218318 小时前
【算法】双指针与滑动窗口(二):滑动窗口——吃进、判定、吐出
算法·leetcode·双指针·滑动窗口·原理·模板·算法讲解
铭哥的编程日记8 小时前
从一道 LeetCode Hard 到吃透一类题:加权区间调度「排序 + 二分 + DP」
算法·leetcode·职场和发展