成果被他人窃取_工作窃取模式

成果被他人窃取_工作窃取模式什么是ForkJoin、ForkJoin分支合并、ForkJoin工作窃取、ForkJoin大数据求和计算什么是ForkJoin?ForkJoin:分支合并ForkJoin特点:工作窃取如何让使用ForkJoinForkJoin求和计算Demo什么是ForkJoin?ForkJoin(分支合并)是jdk1.7之后出来的,并行执行任务,提高效率,用在大数据量场景下。大数据:MapReduce(把大任务拆分成多个小任务,怎么拆分用到了二分算法),每个小任务得出自己的结果,之后再把结果汇总,汇总的过程就是

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

什么是ForkJoin、ForkJoin分支合并、ForkJoin工作窃取、ForkJoin大数据求和计算

什么是ForkJoin?

ForkJoin(分支合并)是jdk1.7之后出来的,并行执行任务,提高效率,用在大数据量场景下。

大数据:Map Reduce(把大任务拆分成多个小任务,怎么拆分用到了二分算法),每个小任务得出自己的结果,之后再把结果汇总,汇总的过程就是分支合并的思想。

ForkJoin:分支合并

ForkJoin会把一个大任务分成若干个小任务去执行(任务是双端队列去存储的,两端都可以操作),然后再合并结果集。
请添加图片描述

ForkJoin特点:工作窃取

ForkJoin会把一个大任务分成若干个小任务去执行(任务是双端队列去存储的,两端都可以操作),然后再合并结果集。
线程的执行速度不一样,因此先执行完的线程,为了避免浪费时间,会去还没有执行完的线程那里拿到它未执行完的任务,去帮它执行,之所以能拿到,也是因为任务是双端队列存储的,两头都可以操作。

ForkJoinPool主要是为了并行计算使用(也就是新增加的并行流),但我觉得更适合IO密集型的场景。
比如大规模的并行查询。而CPU密集型的操作,过多的线程切换可能会影响效率
请添加图片描述

如何让使用ForkJoin

  • 1.ForkJoinPool,通过ForkJoinPool来执行
  • 2.计算任务forkJoinPool.execute(ForkJoinTask task)
  • 3.计算类要继承ForkJoinTask(执行任务RecursiveTask:有返回值 RecursiveAction:无返回值)

Class ForkJoinPool有一个异步执行任务的方法

在这里插入图片描述

在这里插入图片描述

我们需要用到有返回值的RecursiveTask

使用RecursiveTask需要继承RecursiveTask,并定义返回值类型

class Fibonacci extends RecursiveTask<Integer>

ForkJoin求和计算Demo

import java.util.concurrent.*;
import java.util.stream.LongStream;
/** * 求和计算 * 1.最low的:循环求和 * 2.一般的:ForkJoin分支求和 * 3.最快的:Stream并行流求和 */
public class ForkJoinDemo { 

public static void main(String[] args) throws ExecutionException, InterruptedException { 

new ForkJoinDemo().test1();
new ForkJoinDemo().test2();
new ForkJoinDemo().test3();
/** * test1===>和为500000000500000000,耗时9937 * test2===>和为500000000500000000,耗时8622 * test3===>和为500000000500000000,耗时276 */
}
//1.最low的:循环求和
public void test1() { 

long start = System.currentTimeMillis();
Long sum = 0L;
for (Long i = 0L; i <= 10_0000_0000L; i++) { 

sum += i;
}
long end = System.currentTimeMillis();
System.out.println("test1===>和为" + sum + ",耗时" + (end - start));
}
//2.一般的:ForkJoin分支求和
public void test2() throws ExecutionException, InterruptedException { 

long start = System.currentTimeMillis();
// 也可以使用公用的线程池 ForkJoinPool.commonPool():
// pool = ForkJoinPool.commonPool()
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<Long> task = pool.submit(new MySumForkJoin(0L, 10_0000_0000L));//提交任务
Long sum = task.get();
long end = System.currentTimeMillis();
System.out.println("test2===>和为" + sum + ",耗时" + (end - start));
}
//3.最快的:Stream并行流求和
public void test3() { 
//没有Long的拆箱装箱操作
long start = System.currentTimeMillis();
long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0, Long::sum);//reduce第一个参数为0,为了保证,在进行流条件计算下,保证每次累计的值不受多线程影响
long end = System.currentTimeMillis();
System.out.println("test3===>和为" + sum + ",耗时" + (end - start));
}
}
/** * 如何让使用ForkJoin * 1.ForkJoinPool,通过ForkJoinPool来执行 * 2.计算任务forkJoinPool.execute(ForkJoinTask task) * 3.计算类要继承ForkJoinTask(执行任务RecursiveTask:有返回值 RecursiveAction:无返回值) */
class MySumForkJoin extends RecursiveTask<Long> { 

private Long start;//开始值
private Long end;//结束值
private Long criticalValue = 10000L;//临界值,超过这个值开始分任务执行
public MySumForkJoin(Long start, Long end) { 

this.start = start;
this.end = end;
}
//计算方法:递归调用的
@Override
protected Long compute() { 

if (end - start <= criticalValue) { 

Long sum = 0L;
for (Long i = start; i <= end; i++) { 

sum += i;
}
return sum;
} else { 
//ForkJoin执行分支合并计算,
// System.out.println("开始ForkJoin执行分支合并计算");
//1.先求中间值
Long middle = (start + end) / 2;//不直接(start+end)/2,防止溢出
/*把任务一分为二,递归拆分(注意此处有递归)到底拆分成多少分 需要根据具体情况而定*/
MySumForkJoin task1 = new MySumForkJoin(start, middle);
MySumForkJoin task2 = new MySumForkJoin(middle + 1, end);
// task1.fork();//拆分任务,把任务压入双端队列,这里手动只拆分成两个任务,可以拆分多个
// task2.fork();//拆分任务,把任务压入双端队列
invokeAll(task1, task2);//拆分任务,把任务压入双端队列
/** * compute分出多个task后:以task1,task2为例 * 错误做法: * 1)依次执行task1.fork(),task2.fork() * 2)依次执行task1.join(),task2.join() * 正确做法: * 1)直接调用invokeAll(task1,task2) * * fork(): * 把task置入当前ForkJoinWorkerThread的queue中,等待被消费 * join(): * 当前ForkJoinWorkerThread执行等待该task执行结束 * * 错误做法过程: * 将task1与task2置入queue中,当前ForkJoinWorkerThread停下来等待task1,task2的执行结束。 * * 分析: * 当前的ForkJoinWorkerThread可以说join之后什么事情都没有做,只是等待ing。而task1和task2会在新的线程中执行。 * 会浪费当前ForkJoinWorkerThread的宝贵线程资源。而且最糟糕的是,会创建一个新的ForkJoinWorkerThread去执行新的task,可想而知,如果任务量特别多,那会同时开启特别多的线程。 */
return task1.join() + task2.join();
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/194149.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • vs2021安装教程_vs2015企业版安装教程

    vs2021安装教程_vs2015企业版安装教程一、学习C/C++语言用什么环境?DevC++很久不在更新,对于C语言的标准支持不够好vc6.0太古老,98年的软件了二、那小编推荐什么大家用什么软件?VS2013及以上版本都行!今天跟大家唠如何安装VS2022(听说VS官网更新了,小伙伴们找不到VS2019了)三、VS2019下载官网VS2022官网https://visualstudio.microsoft.com/zh-hans/?rr=https://www.microsoft.com/zh-cn/3.1点击VS

  • PHP中unset,array_splice删除数组中元素的区别

    PHP中unset,array_splice删除数组中元素的区别

    2021年10月15日
  • Go环境安装配置

    Go环境安装配置

  • linux抓本来端口包,Linux抓包

    linux抓本来端口包,Linux抓包tcpdump-ieth1-nn‘dsthost172.31.0.42‘-w/tmp/temp.cap监听指定的主机$tcpdump-ieth0-nn‘host192.168.1.231‘这样的话,192.168.1.231这台主机接收到的包和发送的包都会被抓取。$tcpdump-ieth0-nn‘srchost192.168.1.231‘这样只有192….

    2022年10月15日
  • p2p文件服务器,P2P文件传输

    p2p文件服务器,P2P文件传输>网络中的应用,存在两种主流的体系结构。一种是C-S体系,另一种是P2P(对等网)体系。#C-S体系C-S体系是应用很广泛的应用程序体系,如Web应用。在C-S体系中,服务器承担着巨大的责任,需要处理大量的客户端请求,如文件下载请求,这种体系之间**客户端不能直接通信**,而是通过服务器传达。#P2P体系P2P,即peer-to-peer,意思是对等网络。P2P区分于C-S的就是这种体…

  • clion激活码7月【2022.01最新】

    (clion激活码7月)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.html40…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号