教你用Java7的Fork/Join框架开发高并发程序
摘要:Fork/Join框架位于J.U.C(java.util.concurrent)中,是Java7中提供的用于执行并行任务的框架,其可以将大任务分割成若干个小任务,最终汇总每个小任务的结果后得到最终结果。
本文分享自华为云社区《【高并发】如何使用Java7提供的Fork/Join框架实现高并发程序?》,作者:冰 河。
Fork/Join框架
位于J.U.C(java.util.concurrent)中,是Java7中提供的用于执行并行任务的框架,其可以将大任务分割成若干个小任务,最终汇总每个小任务的结果后得到最终结果。基本思想和Hadoop的MapReduce思想类似。
主要采用的是工作窃取算法(某个线程从其他队列里窃取任务来执行),并行分治计算中的一种Work-stealing策略
为什么需要使用工作窃取算法呢?
假如我们需要做一个比较大的任务,我们可以把这个任务分割为若干互不依赖的子任务,为了减少线程间的竞争,于是把这些子任务分别放到不同的队列里,并为每个队列创建一个单独的线程来执行队列里的任务,线程和队列一一对应,比如A线程负责处理A队列里的任务。但是有的线程会先把自己队列里的任务干完,而其他线程对应的队列里还有任务等待处理。干完活的线程与其等着,不如去帮其他线程干活,于是它就去其他线程的队列里窃取一个任务来执行。而在这时它们会访问同一个队列,所以为了减少窃取任务线程和被窃取任务线程之间的竞争,通常会使用双端队列,被窃取任务线程永远从双端队列的头部拿任务执行,而窃取任务的线程永远从双端队列的尾部拿任务执行。
工作窃取算法的优点
充分利用线程进行并行计算,并减少了线程间的竞争
工作窃取算法的缺点
在某些情况下还是存在竞争,比如双端队列里只有一个任务时。并且该算法会消耗更多的系统资源,比如创建多个线程和多个双端队列。
Fork/Join框架局限性
对于Fork/Join框架而言,当一个任务正在等待它使用Join操作创建的子任务结束时,执行这个任务的工作线程查找其他未被执行的任务,并开始执行这些未被执行的任务,通过这种方式,线程充分利用它们的运行时间来提高应用程序的性能。为了实现这个目标,Fork/Join框架执行的任务有一些局限性,如下所示。
- 任务只能使用Fork和Join操作来进行同步机制,如果使用了其他同步机制,则在同步操作时,工作线程就不能执行其他任务了。比如,在Fork/Join框架中,使任务进行了睡眠,那么,在睡眠期间内,正在执行这个任务的工作线程将不会执行其他任务了。
- 在Fork/Join框架中,所拆分的任务不应该去执行IO操作,比如:读写数据文件
- 任务不能抛出检查异常,必须通过必要的代码来出来这些异常
Fork/Join框架的核心类
Fork/Join框架的核心是两个类:ForkJoinPool和ForkJoinTask。ForkJoinPool负责实现工作窃取算法、管理工作线程、提供关于任务的状态以及执行信息。ForkJoinTask主要提供在任务中执行Fork和Join操作的机制。
示例代码
示例代码如下:
package io.binghe.concurrency.example.aqs; import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;
@Slf4j
public class ForkJoinTaskExample extends RecursiveTask<Integer> {
public static final int threshold = 2;
private int start;
private int end;
public ForkJoinTaskExample(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
int sum = 0;
//如果任务足够小就计算任务
boolean canCompute = (end - start) <= threshold;
if (canCompute) {
for (int i = start; i <= end; i++) {
sum += i;
}
} else {
// 如果任务大于阈值,就分裂成两个子任务计算
int middle = (start + end) / 2;
ForkJoinTaskExample leftTask = new ForkJoinTaskExample(start, middle);
ForkJoinTaskExample rightTask = new ForkJoinTaskExample(middle + 1, end); // 执行子任务
leftTask.fork();
rightTask.fork(); // 等待任务执行结束合并其结果
int leftResult = leftTask.join();
int rightResult = rightTask.join(); // 合并子任务
sum = leftResult + rightResult;
}
return sum;
}
public static void main(String[] args) {
ForkJoinPool forkjoinPool = new ForkJoinPool(); //生成一个计算任务,计算1+2+3+4
ForkJoinTaskExample task = new ForkJoinTaskExample(1, 100); //执行一个任务
Future<Integer> result = forkjoinPool.submit(task); try {
log.info("result:{}", result.get());
} catch (Exception e) {
log.error("exception", e);
}
}
}
教你用Java7的Fork/Join框架开发高并发程序的更多相关文章
- Java7提供的Fork/Join框架实现高并发程序,你会使用吗?
摘要:Fork/Join框架位于J.U.C(java.util.concurrent)中,是Java7中提供的用于执行并行任务的框架,其可以将大任务分割成若干个小任务,最终汇总每个小任务的结果后得到最 ...
- 使用Java7提供Fork/Join框架
在Java7在.JDK它提供了多线程开发提供了一个非常强大的框架.这是Fork/Join框架.这是原来的Executors更多 进一步,在原来的基础上添加了并行分治计算中的一种Work-stealin ...
- 使用Java7提供的Fork/Join框架
http://blog.csdn.net/a352193394/article/details/39872923 使用Java7提供的Fork/Join框架 2014-10-07 23:55 4818 ...
- Java7任务并行执行神器:Fork&Join框架
Fork/Join是什么? Fork/Join框架是Java7提供的并行执行任务框架,思想是将大任务分解成小任务,然后小任务又可以继续分解,然后每个小任务分别计算出结果再合并起来,最后将汇总的结果作为 ...
- Java7任务并行执行神器:Fork&Join框架
原 Java7任务并行执行神器:Fork&Join框架 2018年01月12日 17:25:03 Java技术栈 阅读数:426 标签: JAVAFORKJOIN 更多 个人分类: Java ...
- 聊聊并发(八)——Fork/Join框架介绍
作者 方腾飞 发布于 2013年12月23日 | 被首富的“一个亿”刷屏?不如定个小目标,先把握住QCon上海的优惠吧!2 讨论 分享到:微博微信FacebookTwitter有道云笔记邮件分享 ...
- 转:聊聊并发(八)——Fork/Join框架介绍
1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过 ...
- Java并发编程--Fork/Join框架使用
上篇博客我们介绍了通过CyclicBarrier使线程同步,可是上述方法存在一个问题,那就是假设一个大任务跑了2个线程去完毕.假设线程2耗时比线程1多2倍.线程1完毕后必须等待线程2完毕.等待的过程线 ...
- 实现ThreadFactory接口生成自定义的线程给Fork/Join框架
Fork/Join框架是Java7中最有趣的特征之一.它是Executor和ExecutorService接口的一个实现,允许你执行Callable和Runnable任务而不用管理这些执行线程.这个执 ...
- Java 7 Fork/Join 框架
在 Java7引入的诸多新特性中,Fork/Join 框架无疑是重要的一项.JSR166旨在标准化一个实质上可扩展的框架,以将并行计算的通用工具类组织成一个类似java.util中Collection ...
随机推荐
- 【不限框架】超好用的3d开源图片预览插件推荐
今天给大家推荐一款超好用的图片预览插件-image-preview 简单说明 image-preview是一款主要面向移动端web应用,同时兼容pc,基于原生js,不限框架,react,vue,ang ...
- k8s Rabbitmq安装部署
安装方式 kubectl apply -f rabbitmq.yaml -n yunda-dev-cache rabbitmq.yaml ##创建PV # 注意更换存储方式 --- apiVersio ...
- Ansible自动化部署工具-role模式安装filebeat实际案例分析
大家好,我是蓝胖子,前面一节我简单的讲了讲Ansible的架构和编排任务的语法,可以发现,通过playbook方式编排任务时,能够将任务文档化,但是在面对比较复杂且不同业务的任务编排时,维护playb ...
- 物体三维模型的构建:3DSOM软件实现侧影轮廓方法
本文介绍基于3DSOM软件,实现侧影轮廓方法的空间三维模型重建. 目录 1 背景知识 1.1 三维信息获取方法 1.2 侧影轮廓方法原理及其流程 2 三维模型制作 2.1 马铃薯三维模型制作 2. ...
- JavaScript高级程序设计笔记05 基本引用类型
基本引用类型 引用值(对象)是某个特定引用类型的实例.引用类型是把数据和功能组织到一起的结构. 引用类型有时也被称为对象定义,因为它们描述了自己的对象应有的属性和方法. Date 参考了Java早期版 ...
- 品牌全渠道营销系统如何与不同经销商ERP打通
品牌商在与各经销商ERP系统打通方面面临的挑战.传统的ERP系统往往使得数据收集和合作变得繁琐且低效,导致市场响应迟缓,影响整体的供应链管理和市场决策.我们的解决方案旨在破解这一难题,提供一个全渠道营 ...
- 深度解析C#中LinkedList<T>的存储结构
本文承接前面的3篇有关C#的数据结构分析的文章,对于C#有关数据结构分析还有一篇就要暂时结束了,这个系列主要从Array.List.Dictionary.LinkedList. SortedSet等5 ...
- C语言所有运算符及优先级、结合性
C 语言所有运算符及优先级.结合性 参考:<C Primer Plus 第六版> Tip:有关优先级.结合性的表格在最后面. [1]算数运算符 '+'("加号")(二元 ...
- tryhackme进攻性渗透测试-Advanced Exploitation 高级利用
Steel Mountain 侦察 Nmap -sC -sV -O $IP -oN basic_scan.nmap Nmap -script=vuln $IP -oN vuln_scan.nmap 总 ...
- [CF1824D] LuoTianyi and the Function
题目描述 LuoTianyi gives you an array $ a $ of $ n $ integers and the index begins from $ 1 $ . Define $ ...