Fork & Join 的具体含义

Fork 一词的原始含义是吃饭用的叉子,也有分叉的意思。在Linux 平台中,函数 fork()用来创建子进程,使得系统进程可以多一个执行分支。在 Java 中也沿用了类似的命名方式。

而 Join() 的含义和 Thread 类的 join 类似,表示等待。也就是使用 fork() 后系统多了一个执行分支(线程),所以需要等待这个执行分支执行完毕,才有可能得到最终的结果,因此 join 就是表示等待。

在实际使用中,如果毫无顾忌的使用 fork 开启线程进行处理,那么很有可能导致系统开启过多的线程而严重影响性能。所以,在JDK中,给出一个 ForkJoinPool 线程池,对于 fork() 方法并不急着开启线程,而是提交给 ForkJoiinPool 线程池进行处理,以节省系统资源。

由于线程池的优化,提交的任务和线程数量并不是一对一的关系。在绝大多数情况下,一个物理线程实际上是需要处理多个逻辑任务的。因此,每个线程必然需要拥有一个任务队列。因此,在实际执行过程中,可能遇到这么一种情况:线程A已经把自己的任务都处理完了,而线程B还有一堆任务等着处理,此时,线程A就会“帮助” 线程B,从线程 B的任务队列中拿一个任务来处理,尽可能的达到平衡。值得注意的是:当线程试图帮助别人时,总是从任务队列的底部开始拿数据,而线程试图执行自己的任务时,则从相反的顶部开始拿。因此这种行为也十分有利于避免数据竞争。

我们看看线程池 ForkJoinPool 的一个接口:

 /**
* Submits a ForkJoinTask for execution.
*
* @param task the task to submit
* @param <T> the type of the task's result
* @return the task
* @throws NullPointerException if the task is null
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
*/
public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
if (task == null)
throw new NullPointerException();
externalPush(task);
return task;
}

你可以向 ForkJoinPool 线程池提交一个 ForkJoinTask 任务。所谓 ForkJoinTask 任务就是支持 fork () 分解以及 join()等待的任务。 ForkJoinTask 有两个重要的子类,RecursiveAction 和 RecursiveTask。他们分别表示没有返回值的任务和可以携带返回值的任务。有点像 Rannable 和 Callable。

下面来要给简单的例子展示 Fork/Join 框架的使用。这里查找给定的文件夹中,找出最大的文件

1、创建继承RecursiveTask的类

public class ReckonTask extends RecursiveTask<File> {

    private static final long serialVersionUID = 3932273269900797021L;
File path;
Filter filter; public ReckonTask(File path, Filter filter) {
this.path = path;
this.filter = filter;
} @Override
protected File compute() {
File maxFile = null; File[] files = path.listFiles();
for (File file : files) {
if (file.isDirectory()){
ReckonTask reckonTask = new ReckonTask(file,filter);
reckonTask.fork();
maxFile = filter.addFilter(maxFile,reckonTask.join());
}else{
maxFile = filter.addFilter(maxFile,file);
}
}
return maxFile;
}
}

2、创建过滤类Filter

public class Filter {
public File addFilter(File f1, File f2) {
if (null==f1){
return f2;
}else if (null==f2){
return f1;
}
return f1.length()>f2.length()?f1:f2;
}
}

3、调用

public static void main(String[] args) throws ExecutionException, InterruptedException {
long begin = System.currentTimeMillis();
File file = new File("D:\\mavenDB");
ForkJoinPool pool = new ForkJoinPool();
ReckonTask reckonTask = new ReckonTask(file,new MyFilter());
ForkJoinTask<File> submit = pool.submit(reckonTask);
File file1 = submit.get();
long end = System.currentTimeMillis();
System.out.println("路径:"+file1.getPath()+",大小:"+file1.length()+",耗时:"+(end-begin));
//关闭线程池
pool.shutdown();
}

fork/join并发编程的更多相关文章

  1. Fork Join 并发任务执行框架

    Fork Join 体现了分而治之 什么是分而治之? 规模为N的问题,如果N<阈值,直接解决,N>阈值,将N分解为K个小规模子问题,子问题互相对立,与原问题形式相同,将子问题的解合并得到原 ...

  2. 并发编程学习笔记(12)----Fork/Join框架

    1. Fork/Join 的概念 Fork指的是将系统进程分成多个执行分支(线程),Join即是等待,当fork()方法创建了多个线程之后,需要等待这些分支执行完毕之后,才能得到最终的结果,因此joi ...

  3. Java 并发编程 -- Fork/Join 框架

    概述 Fork/Join 框架是 Java7 提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架.下图是网上流传的 Fork Join 的 ...

  4. Java并发编程(07):Fork/Join框架机制详解

    本文源码:GitHub·点这里 || GitEE·点这里 一.Fork/Join框架 Java提供Fork/Join框架用于并行执行任务,核心的思想就是将一个大任务切分成多个小任务,然后汇总每个小任务 ...

  5. java并发编程(10)Fork/Join

    Fork/Join JAVA7中出现的Fork/Join,类似于分布式文件系统hadoop的mapreduce思想,就是将任务分割,再分割,直到分割到满足条件 为了便于理解:编程逻辑可以借用 递归的思 ...

  6. 多线程高并发编程(8) -- Fork/Join源码分析

    一.概念 Fork/Join就是将一个大任务分解(fork)成许多个独立的小任务,然后多线程并行去处理这些小任务,每个小任务处理完得到结果再进行合并(join)得到最终的结果. 流程:任务继承Recu ...

  7. ☕【Java技术指南】「并发编程专题」Fork/Join框架基本使用和原理探究(基础篇)

    前提概述 Java 7开始引入了一种新的Fork/Join线程池,它可以执行一种特殊的任务:把一个大任务拆成多个小任务并行执行. 我们举个例子:如果要计算一个超大数组的和,最简单的做法是用一个循环在一 ...

  8. Java并发编程--Fork/Join框架使用

    上篇博客我们介绍了通过CyclicBarrier使线程同步,可是上述方法存在一个问题,那就是假设一个大任务跑了2个线程去完毕.假设线程2耗时比线程1多2倍.线程1完毕后必须等待线程2完毕.等待的过程线 ...

  9. 转:聊聊并发(八)——Fork/Join框架介绍

    1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过 ...

随机推荐

  1. common pom

    <dependencies> <dependency> <groupId>com.github.pagehelper</groupId> <art ...

  2. nodejs廖雪峰大神教程

    https://www.liaoxuefeng.com/wiki/1022910821149312/1023025235359040

  3. php中美元符号是什么意思

    php中$符号是变量符号: 把$符号加上字符串,这个字符串就是一个变量名或对象名. 其实PHP采用的是C语言的语法,但是也有一些区别,$符号加上字符串,这就是一个变量名或对象名. 例如下面的代码:(推 ...

  4. JS自定义随机键盘

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 文件的上传与下载实现(react、express,create-react-app脚手架)

    项目结构为前后端分离,中间布了一层node. 文件上传 要求:将文件信息等发送到后台. html代码 <input type="file" name="file&q ...

  6. python list,dic,json型字符串转为list,dict,json

    import ast strr='{"1":"A","3":"B"}' dicts= ast.literal_eval( ...

  7. mui初级入门教程(一)— 小白入手mui的学习路线

    文章来源:小青年原创发布时间:2016-05-15关键词:mui,html5+转载需标注本文原始地址:http://zhaomenghuan.github.io/#!/blog/20160515 写在 ...

  8. jmeter之JDBC请求

    jmeter不仅可以测试http请求,也可以执行JDBC请求的测试.本次以mysql为例,介绍JDBC请求如何完成发送 目录 1.环境配置 2.数据库连接配置 3.添加一个JDBC请求 1.环境配置 ...

  9. groub by 与 over partition by 的区别

    这个逻辑,写的很对.明白了这个意思. over partition by 前面一定要用汇总函数.groub by 就可以不用.本质都是汇总 SELECT a.* ,SUM(a.audit_status ...

  10. grpc应用于微服务的分析,基于python

    grpc应用于微服务的分析 gRPC 是一个高性能.开源和通用的 RPC 框架,面向移动和 HTTP/2 设计,目前提供 C.Java 和 Go 语言版本,分别是:grpc, grpc-java, g ...