资讯专栏INFORMATION COLUMN

Java的Fork/Join任务

venmos / 2961人阅读

摘要:方法返回对象,如果任务被取消了则返回。如果任务没有完成或者没有抛出异常则返回。

一. Fork/Join

1 . 简单介绍

a . Fork/Join为JKD1.7引入,适用于对大量数据进行拆分成多个小任务进行计算的框架,最后把所有小任务的结果汇总合并得到最终的结果

b . 相关类

public abstract class RecursiveTask extends ForkJoinTask;
public abstract class RecursiveAction extends ForkJoinTask;

c . 其中RecursiveTask在执行有返回值的任务时使用,RecursiveAction在执行没有返回值的任务时使用

2 . 示例代码

package com.evans;

import com.sun.istack.internal.NotNull;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * Created by Evans
 */
public class SumTask extends RecursiveTask  {
    //默认任务计算限制
    private int taskSize=100;
    //局部变量
    private List sumList;

    public SumTask(@NotNull List list) {
        this.sumList=list;
    }

    public SumTask(@NotNull int taskSize,@NotNull List list) {
        this.taskSize = taskSize;
        this.sumList=list;
    }

    @Override
    protected Long compute() {
        if(this.sumList.size()<=this.taskSize){
            //若集合数量小于限制值则直接计算
            long sum = 0;
            for(Integer item :this.sumList){
                sum += item;
            }
            System.out.println(String.format("Sum List[%d] = %d", this.sumList.size(), sum));
            return sum;
        }
        // 任务大于限制值,则一分为二:
        int middle = (this.sumList.size()) / 2;
        System.out.println(String.format("Split Task List[%d] ==> List[%d], List[%d]", this.sumList.size(), this.sumList.size()-middle,middle));
        SumTask subTask1 = new SumTask(this.taskSize,this.sumList.subList(0,middle));
        SumTask subTask2 = new SumTask(this.taskSize,this.sumList.subList(middle,this.sumList.size()));
        invokeAll(subTask1, subTask2);
        Long subResult1 = subTask1.join();
        Long subResult2 = subTask2.join();
        Long result = subResult1 + subResult2;
        System.out.println("Sum Split Task Result = " + subResult1 + " + " + subResult2 + " ==> " + result);
        return result;
    }

    public static void main(String[] args) {
        //获取当前系统CPU核数
        int coreNumber = Runtime.getRuntime().availableProcessors();
        List originalList = new ArrayList<>();
        for(int i=0;i<100;i++){
            originalList.add(i);
        }
        ForkJoinPool forkJoinPool = new ForkJoinPool(coreNumber);
        ForkJoinTask task = new SumTask(10, originalList);
        long startTime = System.currentTimeMillis();
        Long result = 0L;
        //等待结果返回
        result=forkJoinPool.invoke(task);
        //使用Future 获取结果
//        Future future = forkJoinPool.submit(task);
//        try {
//            result= future.get();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        } catch (ExecutionException e) {
//            e.printStackTrace();
//        }
        long endTime = System.currentTimeMillis();
        System.out.println("Sum Task Result : " + result + " Cost Time : " + (endTime - startTime) + " ms.");
        forkJoinPool.shutdown();
    }
}

控制台输出

Split Task List[100] ==> List[50], List[50]
Sum List[50] = 3725
Sum List[50] = 1225
Sum Split Task Result = 1225 + 3725 ==> 4950
Sum Task Result : 4950 Cost Time : 18 ms.

3 . 备注

a .在有大量计算任务时,此框架方法可进行并行计算效率高,以上示例,可以根据具体的业务需求更改属性及相关方法用于匹配自己的业务逻辑

b .JDK1.8后由于加入Stream流的操作,集合框架可以使用Collection default Stream parallelStream()的方法转换成并行流进行计算,此时效果与Fork/Join任务同效。

c .ForkJoinPool中的多种方法

public  ForkJoinTask submit(ForkJoinTask task);//等待获取结果
public void execute(ForkJoinTask task);//异步执行
public  T invoke(ForkJoinTask task);//执行,获取Future

d .ForkJoinTask在执行的时候可能会抛出异常,但是没办法在主线程里直接捕获异常,所以ForkJoinTask提供了isCompletedAbnormally()方法来检查任务是否已经抛出异常或已经被取消了,并且可以通过ForkJoinTask的getException方法获取异常。getException方法返回Throwable对象,如果任务被取消了则返回CancellationException。如果任务没有完成或者没有抛出异常则返回null。

if(task.isCompletedAbnormally()) {
    System.out.println(task.getException());
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/67403.html

相关文章

  • Java7任务并行执行神器:Fork&Join框架

    摘要:对于任务的分割,要求各个子任务之间相互独立,能够并行独立地执行任务,互相之间不影响。是叉子分叉的意思,即将大任务分解成并行的小任务,是连接结合的意思,即将所有并行的小任务的执行结果汇总起来。使用方法会阻塞并等待子任务执行完并得到其结果。 Fork/Join是什么? Fork/Join框架是Java7提供的并行执行任务框架,思想是将大任务分解成小任务,然后小任务又可以继续分解,然后每个小...

    Luosunce 评论0 收藏0
  • Fork/Join框架

    摘要:框架框架简介框架是提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果得到大任务结果的框架。框架实例需求计算的结果。 Fork/Join框架 1. Fork/Join框架简介 Fork/Join框架是java7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果得到大任务结果的框架。Fork指的就是把一个大任务...

    GitChat 评论0 收藏0
  • Java多线程进阶(四三)—— J.U.C之executors框架:Fork/Join框架(1) 原

    摘要:同时,它会通过的方法将自己注册到线程池中。线程池中的每个工作线程都有一个自己的任务队列,工作线程优先处理自身队列中的任务或顺序,由线程池构造时的参数决定,自身队列为空时,以的顺序随机窃取其它队列中的任务。 showImg(https://segmentfault.com/img/bVbizJb?w=1802&h=762); 本文首发于一世流云的专栏:https://segmentfau...

    cooxer 评论0 收藏0
  • Java 多线程(5):Fork/Join 型线程池与 Work-Stealing 算法

    摘要:时,标准类库添加了,作为对型线程池的实现。类图用来专门定义型任务完成将大任务分割为小任务以及合并结果的工作。 JDK 1.7 时,标准类库添加了 ForkJoinPool,作为对 Fork/Join 型线程池的实现。Fork 在英文中有 分叉 的意思,而 Join 有 合并 的意思。ForkJoinPool 的功能也是如此:Fork 将大任务分叉为多个小任务,然后让小任务执行,Join...

    IamDLY 评论0 收藏0
  • Java多线程进阶(四三)—— J.U.C之executors框架:Fork/Join框架(2)实现

    摘要:并不会为每个任务都创建工作线程,而是根据实际情况构造线程池时的参数确定是唤醒已有空闲工作线程,还是新建工作线程。 showImg(https://segmentfault.com/img/bVbiYSP?w=1071&h=707); 本文首发于一世流云的专栏:https://segmentfault.com/blog... 一、引言 前一章——Fork/Join框架(1) 原理,我们...

    FingerLiu 评论0 收藏0

发表评论

0条评论

venmos

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<