fork/join并发编程
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并发编程的更多相关文章
- Fork Join 并发任务执行框架
Fork Join 体现了分而治之 什么是分而治之? 规模为N的问题,如果N<阈值,直接解决,N>阈值,将N分解为K个小规模子问题,子问题互相对立,与原问题形式相同,将子问题的解合并得到原 ...
- 并发编程学习笔记(12)----Fork/Join框架
1. Fork/Join 的概念 Fork指的是将系统进程分成多个执行分支(线程),Join即是等待,当fork()方法创建了多个线程之后,需要等待这些分支执行完毕之后,才能得到最终的结果,因此joi ...
- Java 并发编程 -- Fork/Join 框架
概述 Fork/Join 框架是 Java7 提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架.下图是网上流传的 Fork Join 的 ...
- Java并发编程(07):Fork/Join框架机制详解
本文源码:GitHub·点这里 || GitEE·点这里 一.Fork/Join框架 Java提供Fork/Join框架用于并行执行任务,核心的思想就是将一个大任务切分成多个小任务,然后汇总每个小任务 ...
- java并发编程(10)Fork/Join
Fork/Join JAVA7中出现的Fork/Join,类似于分布式文件系统hadoop的mapreduce思想,就是将任务分割,再分割,直到分割到满足条件 为了便于理解:编程逻辑可以借用 递归的思 ...
- 多线程高并发编程(8) -- Fork/Join源码分析
一.概念 Fork/Join就是将一个大任务分解(fork)成许多个独立的小任务,然后多线程并行去处理这些小任务,每个小任务处理完得到结果再进行合并(join)得到最终的结果. 流程:任务继承Recu ...
- ☕【Java技术指南】「并发编程专题」Fork/Join框架基本使用和原理探究(基础篇)
前提概述 Java 7开始引入了一种新的Fork/Join线程池,它可以执行一种特殊的任务:把一个大任务拆成多个小任务并行执行. 我们举个例子:如果要计算一个超大数组的和,最简单的做法是用一个循环在一 ...
- Java并发编程--Fork/Join框架使用
上篇博客我们介绍了通过CyclicBarrier使线程同步,可是上述方法存在一个问题,那就是假设一个大任务跑了2个线程去完毕.假设线程2耗时比线程1多2倍.线程1完毕后必须等待线程2完毕.等待的过程线 ...
- 转:聊聊并发(八)——Fork/Join框架介绍
1. 什么是Fork/Join框架 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我们再通过 ...
随机推荐
- FastDFS整合nginx模块报错
之前在本地虚拟机用的都是5.1的版本和1.12的nginx,在服务器上尝试一下高版本的6.1 一直报错各种,例如: undeclared (first use in this function) 尝试 ...
- linux nginx管理
1.添加 Nginx 服务 vim /lib/systemd/system/nginx.service 添加如下内容: [Unit]Description=nginxAfter=network.tar ...
- sqlserver连接-2
本地连接 方法1. 方法2. 远程连接 如果无法通过IP地址远程连接你的SQL Server 2008服务器,可以参考下面的内容进行设置. 在进行下述设置之前,应该确保你的网络已经安装设置完毕,服务器 ...
- GCD 和 NSOperationQueue 的差别
http://stackoverflow.com/questions/10373331/nsoperation-vs-grand-central-dispatch http://www.cocoach ...
- 131、TensorFlow保存模型
# tf.train.Saver类提供了保存和恢复模型的方法 # tf.train.Saver的构造函数 提供了save和恢复的参数选项 # Saver对象提供了方法来运行这些计算节点,制定了写和读的 ...
- 20160122 DataView RowFilter语法
原文出自:http://www.csharp-examples.net/dataview-rowfilter/ DataView RowFilter语法(c#) 这个例子描述了DataView.Row ...
- Openstack_SQLAlchemy 修改数据库的表结构
目录 目录 前言 更改数据库的方法 为数据库添加一张或多张新表 删除一张或多张表 为旧表添加一个字段 为旧表更新一个字段 为旧表初始化一条新的记录 最后 前言 SQLAlchemy 的使用方法和相关基 ...
- mybatis有结果返回null
解决:application.yml 中mybatis此项(解决驼峰及数据库字段有下划线问题) map-underscore-to-camel-case: true 问题: mybatis debug ...
- Jenkins+Git+Gitlab+Ansible实现持续集成自动化部署静态网站
环境准备 三台主机: 一台主机部署jenkins和作为ansible的管理主机 一台主机部署gitlab和ansible的节点1 一台主机为ansible的节点2 防火墙和apache服务关闭 第一步 ...
- HTML--JS 定时刷新、时钟、倒计时
<html> <head> <title>定时刷新时间</title> <script language="JavaScript&quo ...