Java ForkJoin 框架初探

多核时代,编程语言如果不支持多核编程就OUT了,Java为了迎头赶上,在Java 8 版本增加大量支持多核编程的类库,如Stream等,Java 7开始支持的ForkJoin框架也是为了更好的支持多核编程。

设计思想:化整为零再化零为整,另外还要加上一种团队精神,即能者多劳。化整为零(split up)就是把一个复杂的任务分为许多足够小的任务计算;化零为整(merge)就是把小任务的计算结果不断往上合并值到得出最终结果;团队精神:ForkJoin使用了Work-Stealing算法,即先完成任务的线程不会闲着,会主动去偷别的线程待处理任务队列中的任务来帮忙处理,直到全部任务都处理完大伙才能停下来休息。

使用ForkJoin框架经常使用到两个类RecursiveTask 和 RecursiveAction,RecursiveTask 用于定义有返回值的任务,RecursiveAction用于定义没有返回值的任务,从类名看这两个类应该跟递归有一腿?经确认,ForkJoin框架处理的任务基本都能使用递归处理,比如求斐波那契数列等,但递归算法的缺陷是:一只会只用单线程处理,二是递归次数过多时会导致堆栈溢出;ForkJoin解决了这两个问题,使用多线程并发处理,充分利用计算资源来提高效率,同时避免堆栈溢出发生。当然像求斐波那契数列这种小问题直接使用线性算法搞定可能更简单,实际应用中完全没必要使用ForkJoin框架,所以ForkJoin是核弹,是用来对付大家伙的,比如超大数组排序。

最佳应用场景:多核、多内存、可以分割计算再合并的大任务。

ForkJoinTask类的几个重要方法:

fork()方法:将任务放入队列并安排异步执行,一个任务应该只调用一次fork()函数,除非已经执行完毕并重新初始化。

tryUnfork()方法:尝试把任务从队列中拿出单独处理,但不一定成功。

join()方法:等待计算完成并返回计算结果。

isCompletedAbnormally()方法:用于判断任务计算是否发生异常。

ForkJoinPool的使用与其它ExecutorService类似。

示例代码:

package com.stevex.app.forkjoin;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;

public class ForkJoinTest {
	public static void main(String[] args) {
		long beginTime = System.nanoTime();
		System.out.println("The sum from 1 to 1000 is " + sum(1, 1000));
		System.out.println("Time consumed(nano second) By recursive algorithm : " + (System.nanoTime() - beginTime));

		beginTime = System.nanoTime();
		System.out.println("The sum from 1 to 1000000000 is " + sum1(1, 1000000000));
		System.out.println("Time consumed(nano second) By loop algorithm : " + (System.nanoTime() - beginTime));

		ForkJoinTest app = new ForkJoinTest();
		ForkJoinPool forkJoinPool = new ForkJoinPool();
		CountTask task = app.new CountTask(1,1000000000);
		beginTime = System.nanoTime();
		Future<Long> result = forkJoinPool.submit(task);
		try{
			System.out.println("The sum from 1 to 1000000000 is " + result.get());
		}
		catch(Exception e){
			e.printStackTrace();
		}

		System.out.println("Time consumed(nano second) By ForkJoin algorithm : " + (System.nanoTime() - beginTime));
	}

	private static long sum1(long start, long end) {
		long s = 0l;

		for(long i=start; i<= end; i++){
			s += i;
		}

		return s;
	}

	private static long sum(long start, long end){
		if(end > start){
			return end + sum(start, end-1);
		}
		else{
			return start;
		}
	}

	private class CountTask extends RecursiveTask<Long>{
		private static final int THRESHOLD = 10000;
		private int start;
		private int end;

		public CountTask(int start, int end){
			this.start = start;
			this.end = end;
		}

		protected Long compute(){
			//System.out.println("Thread ID: " + Thread.currentThread().getId());

			Long sum = 0l;

			if((end -start) <= THRESHOLD){
				sum = sum1(start, end);
			}
			else{
				int middle = (start + end) / 2;
				CountTask leftTask = new CountTask(start, middle);
				CountTask rightTask = new CountTask(middle + 1, end);
				leftTask.fork();
				rightTask.fork();

				Long leftResult = leftTask.join();
				Long rightResult = rightTask.join();

				sum = leftResult + rightResult;
			}

			return sum;
		}
	}
}
时间: 2024-10-18 21:34:53

Java ForkJoin 框架初探的相关文章

java集合框架初探

Collection接口中的共性功能1.添加 boolean add(object obj);一次添加一个 boolean addAll(Collection);将指定容器中的所有元素添加 2.删除 void clear(); boolean removbe(object o); boolean removeAll(Collection c);3.获取长度 int size()4.判断 boolean isEmpty(); boolean contains(object o) boolean c

java集合框架初探-迭代器

package com.runoob.test; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class IteratorDemo { public static void main(String[] args) { //创建集合 Collection c1=new ArrayList(); c1.add("abc1"); c1.add("

Java之Structs框架初探

今天是小白第一次自己的接触Struts框架,因为网上的资料都是从Structs2开始,跟Structs1完全不同,因此,小白直接跳过1学习版本2的搭建,废话不多说,直接开始. 首先要搭建框架,就肯定要导入一定的资源包,通过小白的查询,知道下面的几个包为必要的. 这里要注意的是,这些包要直接放在web-info下的lib文件夹中,不能嵌套,否则会找不到.还有就是版本的问题,小白之前因为选择了2.4版本,会报一个错误 java.lang.NoClassDefFoundError: org/apach

JAVA并行框架学习之ForkJoin

当硬件处理能力不能按照摩尔定律垂直发展的时候,选择了水平发展,多核处理器已经广泛应用.未来随着技术的进一步发展,可能出现成百上千个处理核心,但现有的程序运行在多核心处理器上并不能得到较大性能的提升,主要的瓶颈在于程序本身的并发处理能力不强,不能够合理的利用多核心资源. 现有的处理方案是从软件入手,试图采用多线程,是程序在同一时间支持多个任务的计算,这种多线程的处理方案在处理器数目较少的情况下可以较为明显的提高应用性能,但我们更加青睐于由硬件实现的多线程处理模式,但这一领域至今没有很好的结果. F

Java并发包线程池之ForkJoinPool即ForkJoin框架(一)

前言 这是Java并发包提供的最后一个线程池实现,也是最复杂的一个线程池.针对这一部分的代码太复杂,由于目前理解有限,只做简单介绍.通常大家说的Fork/Join框架其实就是指由ForkJoinPool作为线程池.ForkJoinTask(通常实现其三个抽象子类)为任务.ForkJoinWorkerThread作为执行任务的具体线程实体这三者构成的任务调度机制.通俗的说,ForkJoin框架的作用主要是为了实现将大型复杂任务进行递归的分解,直到任务足够小才直接执行,从而递归的返回各个足够小的任务

ForkJoin框架

1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过Fork和Join这两个单词来理解下Fork/Join框架,Fork就是把一个大任务切分为若干子任务并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务的结果.比如计算1+2+..+10000,可以分割成10个子任务,每个子任务分别对1000个数进行求和,最终汇总这10个子任务的结果

Java7 Fork-Join 框架:任务切分,并行处理

概要 现代的计算机已经向多CPU方向发展,即使是普通的PC,甚至现在的智能手机.多核处理器已被广泛应用.在未来,处理器的核心数将会发展的越来越多.虽然硬件上的多核CPU已经十分成熟,但是很多应用程序并未这种多核CPU做好准备,因此并不能很好地利用多核CPU的性能优势.为了充分利用多CPU.多核CPU的性能优势,级软基软件系统应该可以充分“挖掘”每个CPU的计算能力,决不能让某个CPU处于“空闲”状态.为此,可以考虑把一个任务拆分成多个“小任务”,把多个"小任务"放到多个处理器核心上并行

Java—集合框架List

集合的概念 现实生活中:很多的事物凑在一起 数学中的集合:具有共同属性的事物的总和 Java中的集合类:是一种工具类,就像是容器,存储任意数量的具有共同属性的对象 集合的作用 在类的内部,对数据进行组织(针对作用与意义一样的属性,将他们放到一个集合中) 简单而快速的搜索大数量的条目 有的集合接口,提供了一系列排列有序的元素,并且可以在序列中快速的插入或删除有关元素 有的集合接口,提供了映射关系,可以通过关键字(key)去快速查找到对应的唯一对象,而这个关键字可以是任意类型 与数组相比 数组的长度

《深入理解Java集合框架》系列文章

Introduction 关于C++标准模板库(Standard Template Library, STL)的书籍和资料有很多,关于Java集合框架(Java Collections Framework, JCF)的资料却很少,甚至很难找到一本专门介绍它的书籍,这给Java学习者们带来不小的麻烦.我深深的不解其中的原因.虽然JCF设计参考了STL,但其定位不是Java版的STL,而是要实现一个精简紧凑的容器框架,对STL的介绍自然不能替代对JCF的介绍. 本系列文章主要从数据结构和算法层面分析