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 ...
随机推荐
- Sa-Token 多账号认证:同时为系统的 Admin 账号和 User 账号提供鉴权操作
Sa-Token 是一个轻量级 java 权限认证框架,主要解决登录认证.权限认证.单点登录.OAuth2.微服务网关鉴权 等一系列权限相关问题. Gitee 开源地址:https://gitee.c ...
- 2021-7-11 Vue的计算属性和侦听器
计算属性是为了让页面显示更加简洁,基于data数据进行处理的方法,以下为实例 <!DOCTYPE html> <html> <head> <title> ...
- 代码随想录算法训练营第三天| LeetCode 203.移除链表元素(同时也对整个单链表进行增删改查操作) 707.设计链表 206.反转链表
203.移除链表元素 题目链接/文章讲解/视频讲解::https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1 ...
- Flask工厂模式蓝图使用Celery实例【亲测可用,已应用于项目中】
单一模式运行Celery在官方文档中已经贴出范例代码,这里我们不过多介绍. 在使用Flaks编写大型项目时,使用工厂模式的好处显而易见.因在Celery4.x以上版本已经抛弃了init_app方法,所 ...
- TCP四次挥手会经历这么多状态
TCP三次握手 中讲述了序列号和建立连接,这一篇来说说释放连接. 标志位 TCP首部中在属性标志位,和建立连接.释放连接有关,位于保留和窗口字段中间,其中三个标识与断开连接有关. ACK: ackno ...
- CSS3新增了哪些选择器?(属性、结构伪类、伪元素选择器)
在css3提供的新选择器之前,选择一个元素需要借助id或者class,css3新增的选择器可以更灵活的去选择需要的元素,那css3提供了哪些好用的选择器呢? 首先就是属性选择器,我们可以通过属性选择器 ...
- 调试linux内核(1): 环境准备和原理介绍
开篇 现在流行的开源项目经历了长时间的开发, 积累了大量的代码, 想要一行一行地阅读代码去学习开源项目, 需要的时间成本是巨大的. 所以, 我们也需要用一种高效的方式去"阅读"代码 ...
- openssh傻瓜式一键自动化更新脚本(ubuntu系统)
鉴于openssh升级太过麻烦,这里自制了一个openssh自动化升级脚本,以root权限一键运行脚本即可: sh openssh-update.sh 注意:这里只使用于ubuntu系统,centos ...
- 抢先体验!超强的 Anchor Positioning 锚点定位
本文,将向大家介绍 CSS 规范中,最新的 Anchor Positioning,翻译为锚点定位. Anchor Position 的出现,极大的丰富了 CSS 的能力,虽然语法稍显复杂,但是有了它, ...
- 淘宝详情api接口的应用
淘宝详情API接口是一个基于HTTP协议的接口服务,可用于获取淘宝商品的具体信息.下面将介绍如何调用淘宝详情API接口获取淘宝商品数据的步骤. 1.注册账号并创建应用 首先,我们需要进行账号注册.实名 ...