首页 / 更多教程 / ForkJoin框架
ForkJoin框架
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了 ForkJoin框架,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3993字,纯文字阅读大概需要6分钟。
内容图文
简介
ForkJoin 是JDK1.7的内容,用于并行执行任务!可以提高效率,特别是在大数据量操作时速率会比普通操作更快!
大数据中:MapReduce 核心思想->把大任务拆分为小任务!
ForkJoin特点:工作窃取
实现原理:双端队列!从上面和下面都可以去拿到任务进行执行!
如下图:线程A和B执行任务,B线程执行完了就可以去执行A线程没有执行完的线程。
不好的地方:如果A线程只有一个线程没有执行完成,B线程执行完成,A线程的最后一个任务会造成AB线程抢这个任务去执行。
示例
- ForkJoinPool的execute方法
- 点击execute的参数:查看ForkJoinTask类的详情
- 接下来的示例我们需要返回值,于是选择ForkJoinTask的子类:RecursiveTask
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.stream.LongStream;
/**
* 如何使用于forkjoin
* 1. 通过 forkjoinPooL来执行
* 2. 计算任务 :forkjoinPooL.execute(ForkJoinTask task)
* 3. 计算类要继承ForkJoinTask
*/
//实现步骤第一步:继承RecursiveTask,指明要返回的值。
public class ForkJoinExample extends RecursiveTask<Long> {
private static final long SUM = 10_0000_0000;
private Long start;
private Long end;
//临界值
private Long temp=10000L;
public ForkJoinExample(Long start, Long end) {
this.start = start;
this.end = end;
}
//实现步骤第二步:实现继承类的抽象方法
@Override
protected Long compute() {
//必须写这个判断:通过debug后我们发现join后又会从新执行compute
if((end-start)<temp){
Long sum=0L;
for (Long i = start; i <=end; i++) {
sum+=i;
}
return sum;
}else {
//中间值
long middle=(start+end)/2;
//将大任务分成两个任务。
ForkJoinExample task1=new ForkJoinExample(start,middle);
task1.fork(); //拆分任务,把任务压入线程队列
ForkJoinExample task2=new ForkJoinExample(middle+1,end);
task2.fork();
//获取结果
return task1.join()+task2.join();
}
}
//测试一使用简单的for循环来
public static void test01(){
long star = System.currentTimeMillis();
long sum = 0L;
for (Long i = 1L; i <= SUM; i++) {
sum+=i;
}
long end = System.currentTimeMillis();
System.out.println("累加结果="+sum);
System.out.println("普通方式执行时间:" + (end-star));
System.out.println("==================");
}
//使用ForkJoin来进行累加操作
public static void test02() throws ExecutionException, InterruptedException {
long star = System.currentTimeMillis();
//实现步骤第三步:使用ForkJoinPool执行
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Long> task = new ForkJoinExample(0L,SUM);
//forkJoinPool.execute(task); execute 没有返回值
ForkJoinTask<Long> submit = forkJoinPool.submit(task);
//使用submit可以获取到结果,但是它有一个阻塞的过程,需要抛出异常
Long sum = submit.get();
System.out.println("累加结果="+sum);
long end = System.currentTimeMillis();
System.out.println("使用forkjoin执行时间:" + (end - star));
System.out.println("==================");
}
//使用stream流来完成,效率是最高的
public static void test03() {
long star = System.currentTimeMillis();
long sum = LongStream.rangeClosed(0L,10_0000_0000L).parallel().reduce(0,Long::sum);
System.out.println(sum);
long end = System.currentTimeMillis();
System.out.println("使用stream流运行时间:" + (end - star));
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
test01();
test02();
test03();
}
}
运行结果
累加结果=500000000500000000
普通方式执行时间:3749
==================
累加结果=500000000500000000
使用forkjoin执行时间:3956
==================
500000000500000000
使用stream流运行时间:326
从结果上我们可以看到使用stream流速度是最快的。
按理来说应该是forkjoin的速度比普通循环更快,但我电脑上结果却是forkjoin较慢。(此处一脸懵逼,求懂的大佬赐教)
注意:forkjoin方式我们并没有看到调用compute(),但是实际上是调用了的,并且每次调用join方法后又会重新执行compute(递归调用)【通过debug方式运行,可以看到这一过程】
基于上面的问题,我将程序中的起始值,最终值和临界值由包装类型Long改为基本类型long,测试结果如下
累加结果=500000000500000000
普通方式执行时间:488
==================
累加结果=500000000500000000
使用forkjoin执行时间:478
==================
500000000500000000
使用stream流运行时间:373
结果显示将操作数改为基本类型Long-long会快很多,通常执行时间还是for>forkjoin>stream
内容总结
以上是互联网集市为您收集整理的 ForkJoin框架全部内容,希望文章能够帮你解决 ForkJoin框架所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。