一、什么是ForkJion

  Fork/Join框架是Java7提供的并行执行任务框架,思想是将大任务分解成小任务,然后小任务又可以继续分解,然后每个小任务分别计算出结果再合并起来,最后将汇总的结果作为大任务结果。其思想和MapReduce的思想非常类似。对于任务的分割,要求各个子任务之间相互独立,能够并行独立地执行任务,互相之间不影响。

二、运行流程图(侵删):

  

三、特点:

  工作窃取-----ForkJion里面是一个双端队列,当A线程运行完自己的任务后,如果B线程没完成,就去B线程的另一端去一个任务来完成

  

四、核心类

  • ForkJoinPool

    ForkJoinPool是ForkJoin框架中的任务调度器,和ThreadPoolExecutor一样实现了自己的线程池,提供了三种调度子任务的方法:

    1. execute:异步执行指定任务,无返回结果;

    2. invoke、invokeAll:异步执行指定任务,等待完成才返回结果;

    3. submit:异步执行指定任务,并立即返回一个Future对象;

  • ForkJoinTask

    Fork/Join框架中的实际的执行任务类,有以下两种实现,一般继承这两种实现类即可。

    1. RecursiveAction:用于无结果返回的子任务;

    2. RecursiveTask:用于有结果返回的子任务;

五、代码实现

  实现1+2+3+...+10亿的和
  

package com.jenne.juc.forkjion;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.stream.LongStream; /**
* 1、forkjoinPool 通过它来执行
* 2、计算任务 forkjoinPool.execute(ForkJoinTask task)
* 3、计算类要继承 ForkJoinTask及其子类
*/ //运行类
public class Demo { public static void main(String[] args) throws ExecutionException, InterruptedException {
test2();
} // 一般操作
public static void test1() {
Long sum = 0L;
long start = System.currentTimeMillis();
for (Long i = 1L; i <= 10_0000_0000; i++) {
sum += i;
}
long end = System.currentTimeMillis();
System.out.println("sum=" + sum + " 时间:" + (end - start));
} // 使用ForkJoin
public static void test2() throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Long> task = new ForkJoinTaskDemo(0L, 10_0000_0000L);
ForkJoinTask<Long> submit = forkJoinPool.submit(task);// 提交任务
Long sum = submit.get();
long end = System.currentTimeMillis();
System.out.println("sum=" + sum + " 时间:" + (end - start));
} //Stream并行流
public static void test3() {
long start = System.currentTimeMillis();
// Stream并行流() (]
long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0, Long::sum);
long end = System.currentTimeMillis();
System.out.println("sum=" + "时间:" + (end - start));
} } //计算类
class ForkJoinTaskDemo extends RecursiveTask<Long> {
private Long start; // 1
private Long end; // 1990900000
// 临界值
private Long temp = 10000L; public ForkJoinTaskDemo(Long start, Long end) {
this.start = start;
this.end = end;
} // 计算方法
@Override
protected Long compute() {
if ((end - start) < temp) {
Long sum = 0L;
for (Long i = start; i <= end; i++) {
sum += i;
}
return sum;
} else { // forkjoin 递归
long middle = (start + end) / 2; // 中间值
ForkJoinTaskDemo task1 = new ForkJoinTaskDemo(start, middle);
task1.fork(); // 拆分任务,把任务压入线程队列
ForkJoinTaskDemo task2 = new ForkJoinTaskDemo(middle + 1, end);
task2.fork(); // 拆分任务,把任务压入线程队列
return task1.join() + task2.join();
}
}
}

JUC---08ForkJion(分支合并)的更多相关文章

  1. 分支合并git checkout adview git merge adview3

    分支合并 git checkout adview git merge adview3

  2. (转)SVN分支/合并原理及最佳实践

    先说说什么是branch.按照Subversion的说法,一个branch是某个development line(通常是主线也即trunk)的一个拷贝,见下图: branch存在的意义在于,在不干扰t ...

  3. ECLIPSE下SVN的创建分支/合并/切换使用

    最近接项目要求,要在svn主干上创建分支,用分支来进行程序的bug修改,而主干上进行新功能的开发.分支上的bug修改完,发布后,可以合并到主干上.项目程序可以在主干和分支之间进行切换,来实现主干和分支 ...

  4. Git 分支合并

    理解核心 Git最初只有一个分支,所有后续分支都是直接或间接的从这个分支切出来的. 在任意两个分支上,向前追溯提交记录,都能找到一个最近的提交同时属于这两个分支,这个提交就是两个分支的分叉节点 分支合 ...

  5. 关于SVN版本分支合并的知识

    分支的合并类型 合并的工作是把主干或者分支上合并范围内的所有改动列出,并对比当前工作副本的内容,由合并者手工修改冲突,然后提交到服务器的相应目录里.如果当前工作副本是主干,则合并的范围是分支上的改动, ...

  6. eclipse中SVN分支合并到主干

    在项目开发中,需要添加一些新的功能,但是又不想影响到其他开发人员的项目进度,所以决定使用SVN分支进行开发,分支开发完毕后再合并到主干.本文介绍如何在eclipse中合并分支到主干. 1. 要想将分支 ...

  7. windows 下svn 创建分支 合并分支 冲突

    我用的系统是win7+Subversion 1.7.4.服务器搭建就略过了,我也是从网上找的,基本上就是几个命令吧!我用的CentOs6.5 .网上找了几个命令搭建很快,基本上是: 1.# sudo  ...

  8. 转 Eclipse下svn的创建分支/合并/切换使用

    最近接项目要求,要在svn主干上创建分支,用分支来进行程序的bug修改,而主干上进行新功能的开发.分支上的bug修改完,发布后,可以合并到主干上.项目程序可以在主干和分支之间进行切换,来实现主干和分支 ...

  9. github 分支 合并

    Git如何进行分支管理?      1.创建分支      创建分支很简单:git branch <分支名>      2.切换分支      git checkout <分支名&g ...

  10. TortoiseSVN 的分支合并操作

    今天对svn的分支合并有了兴趣,所以对新建了一个项目练练手. 在网上找了一篇文章做指导: http://www.open-open.com/lib/view/open1346982569725.htm ...

随机推荐

  1. 并发编程(八)Lock锁

    一.引言 线程并发的过程中,肯定会设计到一个变量共享的概念,那么我们在多线程运行过程中,怎么保证每个先拿获取的变量信息都是最新且有序的呢?这一篇我们来专门学习一下Lock锁. 我们先来了解几个概念: ...

  2. Ubuntu中卸载node和npm并重装

    1.node 和 npm 卸载不干净 #apt-get 卸载 sudo apt-get remove --purge npm sudo apt-get remove --purge nodejs su ...

  3. Spark中的聚类算法

    Spark - Clustering 官方文档:https://spark.apache.org/docs/2.2.0/ml-clustering.html 这部分介绍MLlib中的聚类算法: 目录: ...

  4. 谁说ParameterMap只能读不能写?

    开发过javaweb项目的同学,应该都接触过ServeltRequest吧?ServletRequest接口中有一个方法叫做getParameterMap(),他会返回一个Map<String, ...

  5. vue+less换肤,主题切换方案

    新的项目对于客户自定义要求很高,然后换肤是其中一个很小的模块,经过了一段时间的摸索,看了许多文章,找到了几种方案. https://www.cnblogs.com/leiting/p/11203383 ...

  6. 放弃"指针常量"这种不严谨的中文描述!深度理解数组名、指针常量

    ques1: 数组名完全等价于指针常量吗? int array[10] = { 10,11,12,13,14,15 }; printf("sizeof(array)= %d \n" ...

  7. 在sqlserver中创建表

    1:在sql语句中,临时表有两类,分别是局部(local)和全局(global)临时表,局部临时表只在其会话(事务)中可见,全局临时表可以被会话(事务)中的任何程序或者 模块访问 2:创建局部临时表 ...

  8. python opencv 读取图片 返回图片某像素点的b,g,r值

    转载:https://blog.csdn.net/weixin_41799483/article/details/80884682 #coding=utf-8   #读取图片 返回图片某像素点的b,g ...

  9. matlab进行FIR滤波器设计(一)

    来源:https://blog.csdn.net/leokingszx/article/details/80041910 在实际的应用中,有时需要使用FIR根据完成一些特定功能,比如近似一阶RC低通电 ...

  10. 使用类模板的C++线性表实现(数组方式)

    main.h #ifndef _MAIN_H_ #define _MAIN_H_ #include <iostream> #include <exception> #inclu ...