JUC并发编程学习(十三)ForkJoin
ForkJoin
什么是ForkJoin
ForkJoin在JDK1.7,并发执行任务!大数据量时提高效率。
大数据:Map Reduce(把大任务拆分成小任务)

ForkJoin特点:工作窃取

为什么可以取窃取其他线程的任务呢?因为这里面维护的都是双端队列(即队列的两端都可以取元素)
ForkJoin操作
在java.util.concurrent下的接口摘要中,有以下两个接口


点进其中一个找到具体的类,可以看到ForkJoinPool

这是具体的执行类,就像ThreadPoolExecutor

具体的执行通过ForkJoinTask类来执行

使用ForkJoin
1、需要一个ForkJoinPool,通过execute方法来执行,参数为ForkJoinTask
2、计算任务 forkJoinPool.execute(ForkJoinTask<?> task)
3、定义一个ForkJoinTask

如何去定义一个ForkJoinTask,打开jdk文档,找到ForkJoinTask类,查看具体的子类。

其中递归事件没有返回值,而任务肯定要有结果,所以递归任务是有返回值的
点进任务,查看示例

代码示例:
package org.example.forkjoin;
/*
* 求和计算的任务
*
*
* 程序员的三六九等
* 三(普通求和)、六(ForkJoin)、九(Stream并行流)
*
*
* 使用ForkJoin:
* 1、ForkJoinPoll 通过他来执行
* 2、计算任务 forkJoinPool.execute(ForkJoinTask<?> task)
* 3、定义一个ForkJoinTask
*
*
* */
import java.util.concurrent.RecursiveTask;
public class ForkJoinDemo extends RecursiveTask<Long> {
private Long start;
private Long end;
//临界值
private Long temp = 10000L;
public ForkJoinDemo(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 = (end + start) / 2;//中间值
ForkJoinDemo task1 = new ForkJoinDemo(start,middle);
//拆分任务、把任务压入线程队列
task1.fork();
ForkJoinDemo task2 = new ForkJoinDemo(middle+1,end);
task2.fork();
return task1.join()+task2.join();
}
}
}
三六九等程序员的测试
package org.example.forkjoin;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// test01();//11720
// test02();//7369
test03();//239
}
/*
* 普通程序员
* */
public static void test01() {
long startTime = System.currentTimeMillis();
Long sum = 0L;
for (Long i = 1L; i <= 10_0000_0000L; i++) {
sum+=i;
}
long endTime = System.currentTimeMillis();
System.out.println("结果:" + sum + "-->耗时:" + (endTime - startTime));
}
/*
* 会使用ForkJoin
* */
public static void test02() throws ExecutionException, InterruptedException {
long startTime = System.currentTimeMillis();
ForkJoinDemo forkJoinDemo = new ForkJoinDemo(0L,10_0000_0000L);
ForkJoinPool forkJoinPool = new ForkJoinPool();
// forkJoinPool.execute(forkJoinDemo);//执行
ForkJoinTask<Long> submit = forkJoinPool.submit(forkJoinDemo);
Long aLong = submit.get();
long endTime = System.currentTimeMillis();
System.out.println("结果:" + aLong + "-->耗时:" + (endTime - startTime));
}
/*
* 九等程序员:Stream流并行运算
* 效率高十几倍
*
* */
public static void test03() {
long start = System.currentTimeMillis();
Long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0, Long::sum);
long end = System.currentTimeMillis();
System.out.println("结果:" + sum + "-->耗时:" + (end - start));
}
}
JUC并发编程学习(十三)ForkJoin的更多相关文章
- JUC并发编程学习笔记
JUC并发编程学习笔记 狂神JUC并发编程 总的来说还可以,学到一些新知识,但很多是学过的了,深入的部分不多. 线程与进程 进程:一个程序,程序的集合,比如一个音乐播发器,QQ程序等.一个进程往往包含 ...
- Java并发编程学习前期知识下篇
Java并发编程学习前期知识下篇 通过上一篇<Java并发编程学习前期知识上篇>我们知道了在Java并发中的可见性是什么?volatile的定义以及JMM的定义.我们先来看看几个大厂真实的 ...
- Java并发编程学习笔记
Java编程思想,并发编程学习笔记. 一.基本的线程机制 1.定义任务:Runnable接口 线程可以驱动任务,因此需要一种描述任务的方式,这可以由Runnable接口来提供.要想定义任务,只需实现R ...
- 并发编程学习笔记(15)----Executor框架的使用
Executor执行已提交的 Runnable 任务的对象.此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节.调度等)分离开来的方法.通常使用 Executor 而不是显式地创建 ...
- 并发编程学习笔记(14)----ThreadPoolExecutor(线程池)的使用及原理
1. 概述 1.1 什么是线程池 与jdbc连接池类似,在创建线程池或销毁线程时,会消耗大量的系统资源,因此在java中提出了线程池的概念,预先创建好固定数量的线程,当有任务需要线程去执行时,不用再去 ...
- 并发编程学习笔记(13)----ConcurrentLinkedQueue(非阻塞队列)和BlockingQueue(阻塞队列)原理
· 在并发编程中,我们有时候会需要使用到线程安全的队列,而在Java中如果我们需要实现队列可以有两种方式,一种是阻塞式队列.另一种是非阻塞式的队列,阻塞式队列采用锁来实现,而非阻塞式队列则是采用cas ...
- 并发编程学习笔记(11)----FutureTask的使用及实现
1. Future的使用 Future模式解决的问题是.在实际的运用场景中,可能某一个任务执行起来非常耗时,如果我们线程一直等着该任务执行完成再去执行其他的代码,就会损耗很大的性能,而Future接口 ...
- 并发编程学习笔记(12)----Fork/Join框架
1. Fork/Join 的概念 Fork指的是将系统进程分成多个执行分支(线程),Join即是等待,当fork()方法创建了多个线程之后,需要等待这些分支执行完毕之后,才能得到最终的结果,因此joi ...
- 并发编程学习笔记(10)----并发工具类CyclicBarrier、Semaphore和Exchanger类的使用和原理
在jdk中,为并发编程提供了CyclicBarrier(栅栏),CountDownLatch(闭锁),Semaphore(信号量),Exchanger(数据交换)等工具类,我们在前面的学习中已经学习并 ...
- 并发编程学习笔记(9)----AQS的共享模式源码分析及CountDownLatch使用及原理
1. AQS共享模式 前面已经说过了AQS的原理及独享模式的源码分析,今天就来学习共享模式下的AQS的几个接口的源码. 首先还是从顶级接口acquireShared()方法入手: public fin ...
随机推荐
- 在英特尔 CPU 上微调 Stable Diffusion 模型
扩散模型能够根据文本提示生成逼真的图像,这种能力促进了生成式人工智能的普及.人们已经开始把这些模型用在包括数据合成及内容创建在内的多个应用领域. Hugging Face Hub 包含超过 5 千个预 ...
- MAUI Blazor Android 输入框软键盘遮挡问题2.0
前言 关于MAUI Blazor Android 输入框软键盘遮挡问题,之前的文章已经有了答案,MAUI Blazor Android 输入框软键盘遮挡问题 但是这个方案一直存在一点小的瑕疵 在小窗模 ...
- Easygraph:全面高效的图分析与社会计算开源工具
前言图是对事物之间关系的一种原生的表达,利用图可以深入直接地认识世界中的关联.社交网络.交易数据.知识图谱.交通运输.生物技术等都是图数据的典型应用.社交网络是一种特殊的图数据,它建立在图网络的基础上 ...
- ABP 的ajax请求错误:400 Empty or invalid anti forgery header token.
ABP 的ajax请求错误 记录于2018-03-22 13:31:16 星期四 错误信息:400 Empty or invalid anti forgery header token. 我从网上找到 ...
- .NET Core WebAPI中使用Swagger(完整教程)
一.Swagger简介 1.1-什么是Swagger? Swagger是一个规范且完整的框架,用于生成.描述.调试和可视化Restfull风格的Web服务. Swagger的目标是对Rest API定 ...
- 为react项目添加开发/提交规范(前端工程化、eslint、prettier、husky、commitlint、stylelint)
因历史遗留原因,接手的项目没有代码提醒/格式化,包括 eslint.pretttier,也没有 commit 提交校验,如 husky.commitlint.stylelint,与其期待自己或者同事的 ...
- linux编译安装nginx
前言 系统:centos7和debian11均验证可行 本文将nginx默认支持的编译参数都加上了,所以需要的依赖比较多,酌情配置. 步骤 假设安装在/usr/local/nginx,创建安装目录 m ...
- 解锁Spring组件扫描的新视角
本文分享自华为云社区<Spring高手之路10--解锁Spring组件扫描的新视角>,作者: 砖业洋__. 首先,我们将探讨一些Spring框架中IOC(Inversion of Cont ...
- 程序后台运行方法:使用守护进程 或 screen软件
我们常需要SSH远程登录到Linux 服务器,经常运行一些需要很长时间才能完成的任务,在此期间不能关掉窗口或者断开连接,否则这个任务会被杀掉,一切就半途而废了. 可以使用以下两个方法: 方法一:noh ...
- nflsoj 选数1 2 3
5711 取数-1 状态表示:1维 集合:前 \(i\) 个数里面所有的选法和 属性:所有的选法和的最大值 状态计算:选或不选 选:\(f(i-1)+a_i\) 不选:\(f(i-1)\) #incl ...