Java中的Fork/Join框架使用详解

 更新时间:2024年01月22日 10:45:34   作者:帅气的喵喵  
这篇文章主要介绍了Java中的Fork/Join框架使用详解,Fork/Join 框架:就是在必要的情况下,将一个大任务,进行<BR>拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个<BR>的小任务运算的结果进行 join 汇总,需要的朋友可以参考下

意义

Fork/Join 框架:就是在必要的情况下,将一个大任务,进行 拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个 的小任务运算的结果进行 join 汇总  

Fork/Join 框架与传统线程池的区别

采用 “工作窃取”模式(work-stealing): 当执行新的任务时它可以将其拆分分成更小的任务执行, 并将小任务加到线程队列中,然后再从一个随机线程的队 列中偷一个并把它放在自己的队列中。

相对于一般的线 程池实现,fork/join框架的优势体现在对其中包含的任务的 处理方式上.在一般的线程池中,如果一个线程正在执行的 任务由于某些原因无法继续运行,那么该线程会处于等待 状态、

而在fork/join框架实现中,如果某个子问题由于等 待另外一个子问题的完成而无法继续运行.那么处理该子 问题的线程会主动寻找其他尚未运行的子问题来执行.这 种方式减少了线程的等待时间,提高了性能.  

使用

ForkJoinTask:我们要使用 Fork/Join 框架,首先需要创建一个 ForkJoin 任务。

该类提供了在任务中执行 fork 和 join 的机制。通常情况下我们不需要直接集成 ForkJoinTask 类,只需要继承它的子类,

  • RecursiveAction:用于没有返回结果的任务
  • RecursiveTask:用于有返回结果的任务
  • ForkJoinPool:ForkJoinTask 需要通过 ForkJoinPool 来执行
  • RecursiveTask: 继承后可以实现递归(自己调自己)调用的任务
class MyTask extends RecursiveTask<Integer> {
    //拆分差值不能超过10,计算10以内运算
    private static final Integer VALUE = 10;
    private int begin ;//拆分开始值
    private int end;//拆分结束值
    private int result ; //返回结果
    //创建有参数构造
    public MyTask(int begin,int end) {
        this.begin = begin;
        this.end = end;
    }
    //拆分和合并过程
    @Override
    protected Integer compute() {
        //判断相加两个数值是否大于10
        if((end-begin)<=VALUE) {
            //相加操作
            for (int i = begin; i <=end; i++) {
                result = result+i;
            }
        } else {//进一步拆分
            //获取中间值
            int middle = begin+(end- begin)/2;
            //拆分左边
            MyTask task01 = new MyTask(begin,middle);
            //拆分右边
            MyTask task02 = new MyTask(middle+1,end);
            //调用方法拆分
            task01.fork();
            task02.fork();
            //合并结果
            result = task01.join()+task02.join();
        }
        return result;
    }
}
public class ForkJoinDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建MyTask对象
        MyTask myTask = new MyTask(0,100);
        //创建分支合并池对象
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinTask<Integer> forkJoinTask = forkJoinPool.submit(myTask);
        //获取最终合并之后结果
        Integer result = forkJoinTask.get();
        System.out.println(result);
        //关闭池对象
        forkJoinPool.shutdown();
    }
}
package com.yxj.java8;
import java.util.concurrent.RecursiveTask;
public class ForkJoinCalculate extends RecursiveTask<Long>{
	/**
	 * 
	 */
	private static final long serialVersionUID = 13475679780L;
	private long start;
	private long end;
	private static final long THRESHOLD = 10000L; //临界值
	public ForkJoinCalculate(long start, long end) {
		this.start = start;
		this.end = end;
	}
	@Override
	protected Long compute() {
		long length = end - start;
		if(length <= THRESHOLD){
			long sum = 0;
			for (long i = start; i <= end; i++) {
				sum += i;
			}
			return sum;
		}else{
			long middle = (start + end) / 2;
			ForkJoinCalculate left = new ForkJoinCalculate(start, middle);
			left.fork(); //拆分,并将该子任务压入线程队列
			ForkJoinCalculate right = new ForkJoinCalculate(middle+1, end);
			right.fork();
			return left.join() + right.join();
		}
	}
}
package com.yxj.java8;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
import org.junit.Test;
public class TestForkJoin {
	@Test
	public void test1(){
		long start = System.currentTimeMillis();
		ForkJoinPool pool = new ForkJoinPool();
		ForkJoinTask<Long> task = new ForkJoinCalculate(0L, 10000000000L);
		long sum = pool.invoke(task);
		System.out.println(sum);
		long end = System.currentTimeMillis();
		System.out.println("耗费的时间为: " + (end - start)); //112-1953-1988-2654-2647-20663-113808
	}
	@Test
	public void test2(){
		long start = System.currentTimeMillis();
		long sum = 0L;
		for (long i = 0L; i <= 10000000000L; i++) {
			sum += i;
		}
		System.out.println(sum);
		long end = System.currentTimeMillis();
		System.out.println("耗费的时间为: " + (end - start)); //34-3174-3132-4227-4223-31583
	}
	@Test
	public void test3(){
		long start = System.currentTimeMillis();
		Long sum = LongStream.rangeClosed(0L, 10000000000L)
							 .parallel()
							 .sum();
		System.out.println(sum);
		long end = System.currentTimeMillis();
		System.out.println("耗费的时间为: " + (end - start)); //2061-2053-2086-18926
	}
}

到此这篇关于Java中的Fork/Join框架使用详解的文章就介绍到这了,更多相关Fork/Join框架内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java字符串拼接的优雅方式实例详解

    Java字符串拼接的优雅方式实例详解

    字符串拼接一般使用“+”,但是“+”不能满足大批量数据的处理,下面这篇文章主要给大家介绍了关于Java字符串拼接的几种优雅方式,需要的朋友可以参考下
    2021-07-07
  • 详解Java的MyBatis框架和Spring框架的整合运用

    详解Java的MyBatis框架和Spring框架的整合运用

    在Web端的SSH框架整合中Spring主要负责数据库处理,而引入MyBatis后二者的集成使用效果更佳,下面我们就来详解Java的MyBatis框架和Spring框架的整合运用
    2016-06-06
  • Java Swing实现扫雷小游戏

    Java Swing实现扫雷小游戏

    这篇文章主要为大家详细介绍了Java Swing实现扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-07-07
  • Java Objects工具类原理及用法详解

    Java Objects工具类原理及用法详解

    这篇文章主要介绍了Java Objects工具类原理及用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • Java计算数学表达式代码详解

    Java计算数学表达式代码详解

    这篇文章主要介绍了Java计算数学表达式代码详解,具有一定借鉴价值,需要的朋友可以了解下。
    2017-12-12
  • idea配置maven环境时maven下载速度慢的解决方法

    idea配置maven环境时maven下载速度慢的解决方法

    我们在idea配置maven环境的时候会发现maven更新慢的现象,解决办法就是下载国内的镜像包,完美解决下载速度慢的问题,文中有详细的具体操作方法,并通过图文介绍的非常详细,需要的朋友可以参考下
    2024-02-02
  • Resty极简restful框架快速接入Spring

    Resty极简restful框架快速接入Spring

    这篇文章主要为大家介绍了Resty极简的restful框架快速接入Spring详细说明,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03
  • java实现员工工资管理系统

    java实现员工工资管理系统

    这篇文章主要为大家详细介绍了java实现员工工资管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • java实现word文档转pdf并添加水印的方法详解

    java实现word文档转pdf并添加水印的方法详解

    这篇文章主要介绍了java实现word文档转pdf并添加水印的方法,结合实例形式详细分析了java word文档转PDF相关实现技巧与操作注意事项,需要的朋友可以参考下
    2019-09-09
  • ArrayList详解和使用示例_动力节点Java学院整理

    ArrayList详解和使用示例_动力节点Java学院整理

    ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态增长。接下来通过本文给大家介绍arraylist详解和使用示例代码,需要的的朋友一起学习吧
    2017-05-05

最新评论