许多情况下,在一个程序中使用多线程是有益处的,可以大大提高程序的效率,多线程主要有以下3个优点1,资源利用率更好2,程序设计在某些情况下更简单3,程序响应更快。当然凡事有利就有弊,多线程也会使程序的开发,维护及调试更加复杂,当然如果我们能够扬长避短,在正确的场合下使用多线程,那么它将成为我们程序中开发的利器。

Java一直以来,对多线程的开发支持比较良好,特别在JDK5,6后引入的java.util.concurrent包,使用多线程的开发变的更加容易,这个包里面大部分的API都是更进一步的封装,作为开发者,我们只需熟悉它怎么使用,就能够很轻松的上手,当然如果你想完全搞懂它,那么就需要读读那些优秀的源码了。

ForkJoinPool这个类是JDK7后新增的线程池,很适合在单机多核的PC上部署多线程程序,ForkJoinPool使用的分而治之的思想,这一点与当前很火的大数据处理框架Hadoop的map/reduce思想非常类似,但是他们的使用场合却不一样,ForkJoinPool适合在一台PC多核CPU上运行,而hadoop则适合在分布式环境中进行大规模集群部署。

Fork/Join 模式有自己的适用范围。如果一个应用能被分解成多个子任务,并且组合多个子任务的结果就能够获得最终的答案,那么这个应用就适合用 Fork/Join 模式来解决.

ForkJoinPool使用的工作窃取的方式能够在最大方式上充分利用CPU的资源,一般流程是fork分解,join结合。本质是将一个任务分解成多个子任务,每个子任务用单独的线程去处理,主要几个常用方法有

关于上表中的ForkJoinTask是一个抽象类,代表一个可以fork与join的任务. ,它还有2个抽象子类:RecursiveAcion和RecursiveTask.其中RecursiveTask代表有泛型返回值的任务.而RecursiveAction代表没有返回值.

package com.demo;  import java.util.concurrent.RecursiveAction;  /** *  * 继承RecursiveAction来实现可分解的任务 * 注意无返回值 *  * **/  public class PrintTask extends RecursiveAction {  //每个小任务,最多只打印50个数  private static final int threshold=50;  //打印任务的开始  private int start;  //打印任务的结束  private int end;  public PrintTask() {  // TODO Auto-generated constructor stub  }  //打印从start到end之间的任务  public PrintTask(int start, int end) {  super();  this.start = start;  this.end = end;  }  @Override  protected void compute() {  if(end-start<threshold){  for(int i=start;i<end;i++){  System.out.println(Thread.currentThread().getName()+"i的值:"+i);  }  }else{  //当end与start之间的差大于threshold,及打印的数超过50个时,  //将大任务分解成2个小任务  int middle=(start+end)/2;  PrintTask left=new PrintTask(start, middle);  PrintTask  right=new PrintTask(middle, end);  //并行执行两个小任务  left.fork();  right.fork();  }  }  }

有返回值的demo

package com.demo;  import java.util.concurrent.RecursiveTask;
/*** * 有返回值 *  * */
public class CalTask  extends RecursiveTask<Integer>{  //将每个小任务,最多只能累加20个数  private static final int threshold=20;  private int arr[];  private int start;//开始  private int end;//  //累加从start到end之间的数  public CalTask() {  // TODO Auto-generated constructor stub  }  //累加从start到end的数组元素  public CalTask(int[] arr, int start, int end) {  super();  this.arr = arr;  this.start = start;  this.end = end;  }  @Override  protected Integer compute() {  int sum=0;  //当end与start之间的差小于threshold,开始进行累加  if(end-start<threshold){  for(int i=start;i<end;i++){  sum+=arr[i];  }  return sum;  }else{  //当end与start之间的差大于threshold,要计算的数超过20个时,  //将大任务分解成两个小任务  int middle=(start+end)/2;  CalTask left=new CalTask(arr, start, middle);  CalTask right=new CalTask(arr, middle, end);  //并行执行2个小任务  left.fork();  right.fork();  //把2个小任务,累加的结果合并起来  return left.join()+right.join();  }  }  }
package com.demo;  import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;  public class Sum {  public static void main(String[] args)throws Exception {  int []arr=new int[1100];  Random rand=new Random();  int total=0;  //初始化100个数字  for(int i=0;i<arr.length;i++){  int tmp=rand.nextInt(20);  //对元素赋值,并将数组元素的值添加到total总和中  total+=(arr[i]=tmp);  }  System.out.println("正确的total:"+total);  ForkJoinPool pool=new ForkJoinPool();  //提交可分解的CalTask任务  Future<Integer> future=pool.submit(new CalTask(arr, 0, arr.length));  System.out.println(future.get());  //关闭线程池  pool.shutdown();  }  }

Java7之线程池ForkJoinPool相关推荐

  1. ForkJoinPool线程池

    在Java 7中引入了一种新的线程池:ForkJoinPool. 它同ThreadPoolExecutor一样,也实现了Executor和ExecutorService接口.它使用了一个无限队列来保存 ...

  2. Tomcat线程池和ForkJoinPool线程池

    目录 Tomcat线程池 这里线程分了三个部分: Tomcat线程池与ThreadPoolExecutor的区别: 一些注意参数: Fork/Join线程池 ForkJoinPool 发送信息 例子: ...

  3. 中fifo算法_java线程池,工作窃取算法

    前言 在上一篇<java线程池,Executors阿里开发规范中为什么禁止使用Executors?>中我们谈及了线程池,同时又发现一个现象,当最大线程数还没有满的时候耗时的任务全部堆积给了 ...

  4. Java多线程及线程池

    1.volatile 内存模型的相关概念 Java并发编程:volatile关键字解析 - Matrix海子 - 博客园 (cnblogs.com) 在JVM底层volatile是采用"内存 ...

  5. Java多线程学习七:线程池的 4 种拒绝策略和 6 种常见的线程池

    以便在必要的时候按照我们的策略来拒绝任务,那么拒绝任务的时机是什么呢?线程池会在以下两种情况下会拒绝新提交的任务. 第一种情况是当我们调用 shutdown 等方法关闭线程池后,即便此时可能线程池内部 ...

  6. Java六大线程池和四大拒绝策略

    Java六大线程池和四大拒绝策略 学习常见的 6 种线程池,并详细讲解 Java 8 新增的 ForkJoinPool 线程池,6 种常见的线程池如下. FixedThreadPool CachedT ...

  7. 多线程之 ForkJoinool线程池(二十四)

    "分而治之"的一个有效的处理大数据的方法,著名的MapReduce就是采用这种分而治之的思路,简单点生活如果要处理的1000个数据,但是我们不具备处理1000个数据的能量,可以处理 ...

  8. java8 forkjoinpool_Java 普通线程池与 ForkJoinPool 的效果对比

    Java 多线程编程常用的一个接口是 ExecutorService, 其实就一个线程池的接口,一般由两种方式创建线程池,一为 Executors 的工厂方法,二则创建 ForkJoinPool 实例 ...

  9. 线程及同步的性能 – 线程池/ ThreadPoolExecutors/ ForkJoinPool

    线程池和ThreadPoolExecutors 虽然在程序中可以直接使用Thread类型来进行线程操作,但是更多的情况是使用线程池,尤其是在Java EE应用服务器中,一般会使用若干个线程池来处理来自 ...

最新文章

  1. python-global全局变量
  2. 新增Skin-watercolor
  3. Java垃圾回收(2)
  4. 数据结构拾遗(2) --红黑树的设计与实现(中)
  5. python paramiko并发_Python之paramiko
  6. 人工蜂群算法的最小搜索模型_【优化求解】人工蜂群ABC算法
  7. Unity官方案例精讲_2015_优化
  8. 如何判断视频数据是H264编码
  9. 智慧城市——智慧社区解决方案
  10. 开始时间 结束时间,全程的运行时间的计算
  11. Electron 仿制WeGame(二)
  12. JAVA钓鱼游戏_java实现小猫钓鱼游戏
  13. 有什么好玩的网页小游戏网站推荐么?
  14. Docker 启动nginx报错Error starting userland proxy: listen tcp 0.0.0.0:80: bind: address already in use.
  15. OPENGL 简单图形绘制
  16. 2018铁三测评题write以及一些想送给你们的话
  17. matlab中imag什么意思,Matlab基本函数-imag函数
  18. 显卡组超级计算机,NVIDIA发布全新显卡 在家就能拥有超级计算机
  19. C++:数组、链表与哈希表
  20. 什么是类、什么是对象

热门文章

  1. 知识图谱学习笔记-风控算法介绍
  2. 数学知识复习:二阶导复合函数的链式法则
  3. 强化学习笔记:Policy-based Approach
  4. NTU课程:MAS714 (3)Graph Algorithms
  5. python实现三叉树_使用python代码实现三叉搜索树高效率”自动输入提示”功能
  6. Python入门100题 | 第073题
  7. 解决服务器连接错误Host ‘XXX’ is not allowed to connect to this MySQL server
  8. 【LeetCode从零单排】No96 Unique Binary Search Trees
  9. vim学习笔记一(环境配置及编译文件)
  10. spring websocket源码分析续Handler的使用