Java7之线程池ForkJoinPool
许多情况下,在一个程序中使用多线程是有益处的,可以大大提高程序的效率,多线程主要有以下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相关推荐
- ForkJoinPool线程池
在Java 7中引入了一种新的线程池:ForkJoinPool. 它同ThreadPoolExecutor一样,也实现了Executor和ExecutorService接口.它使用了一个无限队列来保存 ...
- Tomcat线程池和ForkJoinPool线程池
目录 Tomcat线程池 这里线程分了三个部分: Tomcat线程池与ThreadPoolExecutor的区别: 一些注意参数: Fork/Join线程池 ForkJoinPool 发送信息 例子: ...
- 中fifo算法_java线程池,工作窃取算法
前言 在上一篇<java线程池,Executors阿里开发规范中为什么禁止使用Executors?>中我们谈及了线程池,同时又发现一个现象,当最大线程数还没有满的时候耗时的任务全部堆积给了 ...
- Java多线程及线程池
1.volatile 内存模型的相关概念 Java并发编程:volatile关键字解析 - Matrix海子 - 博客园 (cnblogs.com) 在JVM底层volatile是采用"内存 ...
- Java多线程学习七:线程池的 4 种拒绝策略和 6 种常见的线程池
以便在必要的时候按照我们的策略来拒绝任务,那么拒绝任务的时机是什么呢?线程池会在以下两种情况下会拒绝新提交的任务. 第一种情况是当我们调用 shutdown 等方法关闭线程池后,即便此时可能线程池内部 ...
- Java六大线程池和四大拒绝策略
Java六大线程池和四大拒绝策略 学习常见的 6 种线程池,并详细讲解 Java 8 新增的 ForkJoinPool 线程池,6 种常见的线程池如下. FixedThreadPool CachedT ...
- 多线程之 ForkJoinool线程池(二十四)
"分而治之"的一个有效的处理大数据的方法,著名的MapReduce就是采用这种分而治之的思路,简单点生活如果要处理的1000个数据,但是我们不具备处理1000个数据的能量,可以处理 ...
- java8 forkjoinpool_Java 普通线程池与 ForkJoinPool 的效果对比
Java 多线程编程常用的一个接口是 ExecutorService, 其实就一个线程池的接口,一般由两种方式创建线程池,一为 Executors 的工厂方法,二则创建 ForkJoinPool 实例 ...
- 线程及同步的性能 – 线程池/ ThreadPoolExecutors/ ForkJoinPool
线程池和ThreadPoolExecutors 虽然在程序中可以直接使用Thread类型来进行线程操作,但是更多的情况是使用线程池,尤其是在Java EE应用服务器中,一般会使用若干个线程池来处理来自 ...
最新文章
- python-global全局变量
- 新增Skin-watercolor
- Java垃圾回收(2)
- 数据结构拾遗(2) --红黑树的设计与实现(中)
- python paramiko并发_Python之paramiko
- 人工蜂群算法的最小搜索模型_【优化求解】人工蜂群ABC算法
- Unity官方案例精讲_2015_优化
- 如何判断视频数据是H264编码
- 智慧城市——智慧社区解决方案
- 开始时间 结束时间,全程的运行时间的计算
- Electron 仿制WeGame(二)
- JAVA钓鱼游戏_java实现小猫钓鱼游戏
- 有什么好玩的网页小游戏网站推荐么?
- Docker 启动nginx报错Error starting userland proxy: listen tcp 0.0.0.0:80: bind: address already in use.
- OPENGL 简单图形绘制
- 2018铁三测评题write以及一些想送给你们的话
- matlab中imag什么意思,Matlab基本函数-imag函数
- 显卡组超级计算机,NVIDIA发布全新显卡 在家就能拥有超级计算机
- C++:数组、链表与哈希表
- 什么是类、什么是对象
热门文章
- 知识图谱学习笔记-风控算法介绍
- 数学知识复习:二阶导复合函数的链式法则
- 强化学习笔记:Policy-based Approach
- NTU课程:MAS714 (3)Graph Algorithms
- python实现三叉树_使用python代码实现三叉搜索树高效率”自动输入提示”功能
- Python入门100题 | 第073题
- 解决服务器连接错误Host ‘XXX’ is not allowed to connect to this MySQL server
- 【LeetCode从零单排】No96	Unique Binary Search Trees
- vim学习笔记一(环境配置及编译文件)
- spring websocket源码分析续Handler的使用