java-forkjoin框架的使用
ForkJoin是Java7提供的原生多线程并行处理框架,其基本思想是将大任务分割成小任务,最后将小任务聚合起来得到结果。fork是分解的意思, join是收集的意思. 它非常类似于HADOOP提供的MapReduce框架,只是MapReduce的任务可以针对集群内的所有计算节点,可以充分利用集群的能力完成计算任务。ForkJoin更加类似于单机版的MapReduce。
在fork/join框架中,若某个子问题由于等待另一个子问题的完成而无法继续执行。那么处理该子问题的线程会主动寻找其他尚未运行完成的子问题来执行。这种方式减少了线程的等待时间,提高了性能。子问题中应该避免使用synchronized关键词或其他方式方式的同步。也不应该是一阻塞IO或过多的访问共享变量。在理想情况下,每个子问题的实现中都应该只进行CPU相关的计算,并且只适用每个问题的内部对象。唯一的同步应该只发生在子问题和创建它的父问题之间。
Fork/Join使用两个类完成以上两件事情:
- . RecursiveAction,用于没有返回结果的任务
- . RecursiveTask,用于有返回值的任务
源码推荐查询 jdk8的
· ForkJoinPool:task要通过ForkJoinPool来执行,分割的子任务也会添加到当前工作线程的双端队列中,进入队列的头部。当一个工作线程中没有任务时,会从其他工作线程的队列尾部获取一个任务。
2个构造方法
- ForkJoinPool(int parallelism) 创建一个包含parallelism个并行线程的ForkJoinPool。
- ForkJoinPool() 以Runtime.availableProcessors()方法的返回值作为parallelism参数来创建ForkJoinPool。
3种方式启动
- 异步执行 execute(ForkJoinTask) ForkJoinTask.fork
- 等待获取结果 invoke(ForkJoinTask) ForkJoinTask.invoke
- 执行,获取Future submit(ForkJoinTask) ForkJoinTask.fork(ForkJoinTask are Futures)
异常处理:
ForkJoinTask在执行的时候可能会抛出异常,但是没办法在主线程里直接捕获异常,所以ForkJoinTask提供了isCompletedAbnormally()方法来检查任务是否已经抛出异常或已经被取消了,并且可以通过ForkJoinTask的getException方法获取异常.
getException方法返回Throwable对象,如果任务被取消了则返回CancellationException。如果任务没有完成或者没有抛出异常则返回null。
- if(task.isCompletedAbnormally()) {
- System.out.println(task.getException());
- }
然后, 代码展示
- import java.util.concurrent.ForkJoinPool
- import java.util.concurrent.ForkJoinTask
- import java.util.concurrent.RecursiveTask
- /**
- * fork
- * 对一个大数组进行并行求和的RecursiveTask
- *
- * 大任务可以拆成小任务,小任务还可以继续拆成更小的任务,最后把任务的结果汇总合并,得到最终结果,这种模型就是Fork/Join模型。
- Java7引入了Fork/Join框架,我们通过RecursiveTask这个类就可以方便地实现Fork/Join模式。
- * Created by wenbronk on 2017/7/13.
- */
- class ForkJoinTest extends RecursiveTask<Long> {
- static final int THRESHOLD =
- long[] array
- int start
- int end
- ForkJoinTest(long[] array, int start, int end) {
- this.start = start
- this.end = end
- this.array = array
- }
- @Override
- protected Long compute() {
- if (end - start < THRESHOLD) {
- long sum =
- for (int i = start; i < end; i++) {
- sum += array[i]
- }
- try {
- Thread.sleep()
- } catch (Exception e) {
- e.printStackTrace()
- }
- println String.format('compute %d %d = %d', start, end, sum)
- }
- // 对于大任务, 分多线程执行
- int middle = (end + start) /
- println String.format('split %d %d => %d %d, %d %d', start, end, start, middle, middle, end)
- def subtask1 = new ForkJoinTest(this.array, start, middle);
- def subtask2 = new ForkJoinTest(this.array, middle, end);
- invokeAll(subtask1, subtask2)
- Long subresult1 = subtask1.join()
- Long subresult2 = subtask2.join()
- Long result = subresult1 + subresult2
- System.out.println("result = " + subresult1 + " + " + subresult2 + " ==> " + result);
- return result
- }
- public static void main(String[] args) throws Exception {
- // 创建随机数组成的数组:
- long[] array = new long[];
- // fillRandom(array);
- // fork/join task:
- ForkJoinPool fjp = new ForkJoinPool(); // 最大并发数4
- ForkJoinTask<Long> task = new ForkJoinTest(array, , array.length);
- long startTime = System.currentTimeMillis();
- Long result = fjp.invoke(task);
- long endTime = System.currentTimeMillis();
- System.out.println("Fork/join sum: " + result + " in " + (endTime - startTime) + " ms.");
- }
- }
java代码的实现
- package com.wenbronk.test;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.ForkJoinPool;
- import java.util.concurrent.ForkJoinTask;
- import java.util.concurrent.RecursiveTask;
- /**
- * forkjoin的简单易用
- * Created by wenbronk on 2017/7/26.
- */
- public class CountTask extends RecursiveTask<Integer>{
- private volatile static int count = ;
- private int start;
- private int end;
- public CountTask(int start, int end) {
- this.start = start;
- this.end = end;
- }
- public static final int threadhold = ;
- @Override
- protected Integer compute() {
- int sum = ;
- System.out.println("开启了一条线程单独干: " + count++);
- // 如果任务足够小, 就直接执行
- boolean canCompute = (end - start) <= threadhold;
- if (canCompute) {
- for (int i = start; i <= end; i++) {
- sum += i;
- }
- }else {
- //任务大于阈值, 分裂为2个任务
- int middle = (start + end) / ;
- CountTask countTask1 = new CountTask(start, middle);
- CountTask countTask2 = new CountTask(middle + , end);
- // 开启线程
- // countTask1.fork();
- // countTask2.fork();
- invokeAll(countTask1, countTask2);
- Integer join1 = countTask1.join();
- Integer join2 = countTask2.join();
- // 结果合并
- sum = join1 + join2;
- }
- return sum;
- }
- // 测试
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- ForkJoinPool forkJoinPool = new ForkJoinPool();
- CountTask countTask = new CountTask(, );
- ForkJoinTask<Integer> result = forkJoinPool.submit(countTask);
- System.out.println(result.get());
- }
- }
java-forkjoin框架的使用的更多相关文章
- java fork-join框架应用和分析
http://shmilyaw-hotmail-com.iteye.com/blog/1897636 java fork-join框架应用和分析 博客分类: concurrency multithre ...
- JAVA并行框架学习之ForkJoin
当硬件处理能力不能按照摩尔定律垂直发展的时候,选择了水平发展,多核处理器已经广泛应用.未来随着技术的进一步发展,可能出现成百上千个处理核心,但现有的程序运行在多核心处理器上并不能得到较大性能的提升,主 ...
- Java并发编程原理与实战三十二:ForkJoin框架详解
1.Fork/Join框架有什么用呢? ------->Fork使用来切分任务,Join是用来汇总结果.举个简单的栗子:任务是1+2+3+...+100这个任务(当然这个任务的结果有好的算法去做 ...
- Java并发包线程池之ForkJoinPool即ForkJoin框架(一)
前言 这是Java并发包提供的最后一个线程池实现,也是最复杂的一个线程池.针对这一部分的代码太复杂,由于目前理解有限,只做简单介绍.通常大家说的Fork/Join框架其实就是指由ForkJoinPoo ...
- ForkJoin框架
1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过 ...
- Java7 Fork-Join 框架:任务切分,并行处理
概要 现代的计算机已经向多CPU方向发展,即使是普通的PC,甚至现在的智能手机.多核处理器已被广泛应用.在未来,处理器的核心数将会发展的越来越多.虽然硬件上的多核CPU已经十分成熟,但是很多应用程序并 ...
- JUC组件扩展(二)-JAVA并行框架Fork/Join(三):在任务中抛出异常
在java当中,异常一共分为两种.一种是运行时异常,一种是非运行是异常. 非运行时异常:这些异常必须在方法上通过throws子句抛出.或者在方法体内进行try{…}catch{…}来捕获异常. 运行时 ...
- Java--8--新特性--串并行流与ForkJoin框架
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流.穿行流则相反,并行流的底层其实就是ForkJoin框架的一个实现. 那么先了解一下ForkJoin框架吧. Fork/Join ...
- Java集合框架List,Map,Set等全面介绍
Java集合框架的基本接口/类层次结构: java.util.Collection [I]+--java.util.List [I] +--java.util.ArrayList [C] +- ...
- Java集合框架练习-计算表达式的值
最近在看<算法>这本书,正好看到一个计算表达式的问题,于是就打算写一下,也正好熟悉一下Java集合框架的使用,大致测试了一下,没啥问题. import java.util.*; /* * ...
随机推荐
- PAT甲 1032. Sharing (25) 2016-09-09 23:13 27人阅读 评论(0) 收藏
1032. Sharing (25) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue To store Engl ...
- PAT甲 1002. A+B for Polynomials (25) 2016-09-09 22:50 64人阅读 评论(0) 收藏
1002. A+B for Polynomials (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue T ...
- Javascript设计模式理论与实战:观察者模式
观察者模式主要应用于对象之间一对多的依赖关系,当一个对象发生改变时,多个对该对象有依赖的其他对象也会跟着做出相应改变,这就非常适合用观察者模式来实现.使用观察者模式可以根据需要增加或删除对象,解决一对 ...
- C#模拟请求,模拟登录,Cookie设置、文件上传等问题汇总
由于业务需求,最近需要模拟完成登陆某个网站,并上传所需要的文件.在开发途中,遇到了很多问题,现在,就我遇到的一些问题及解决办法说明如下,希望对遇到同样问题的人有所帮助.因为技术有限,可能有些内容并不完 ...
- Kafka consumer的参数
earliest: 当各分区下有已提交的offset时,从提交的offset开始消费:无提交的offset时,从头开始消费 latest :当各分区下有已提交的offset时,从提交的offset开始 ...
- 我的第一个网络爬虫 C#版 福利 程序员专车
最近在自觉python,看到了知乎上一篇文章(https://www.zhihu.com/question/20799742),在福利网上爬视频... 由是我就开始跟着做了,但答主给的例子是基于pyt ...
- 如何学习、了解Kubernetes?
欢迎访问网易云社区,了解更多网易技术产品运营经验 [Kubernetes官方文档](https://kubernetes.io/docs/tutorials/)是最基本的入门教材,这里的内容是最官方, ...
- hdu2829 Lawrence
题目链接:戳我 朴素DP:\(dp[i][j]=dp[i-1][k]+cost[k+1][j]\) 其中dp[i][j]表示炸第i次的时候,处理到前j个的最小值是多少.cost[i][j]表示的是i, ...
- Exp2 后门原理与实践 20164321 王君陶
Exp2 后门原理与实践 20164321 王君陶 一.实验内容 基础问题回答: 1.例举你能想到的一个后门进入到你系统中的可能方式? 答:通过漏洞,点击陌生链接,或者浏览不良网页挂马. 2.例举你知 ...
- Axure学习了解
我这次介绍的原型设计工具为Axure 一.区域介绍 这是主界面: 左上区域显示原型的各个界面,可以添加新界面: 左中包含各种原型设计所包含的组件,例如文本框,图片等: 左下是各种模板,模板由自己设计, ...