1.阿姆达尔定律定义
一个程序(或者一个算法)可以按照是否可以被并行化分为下面两个部分:
可以被并行化的部分
不可以被并行化的部分
阿姆达尔定律给出了任务在固定负载的情况下,随着系统资源的提升,执行速度的理论上限。以计算机科学家Gene Amdahl命名。p为串行程序所在比例
·
·
S(N)=1(1−p)+pN
·
·
2. Fork Join
“工作窃取”,也就是设计论文原文中提到的 Work Stealing 。对于负载比较轻的线程,可以帮助负载较重的执行线程分担任务。
任务分解的粒度。和前者有关系,就是分解的任务,“小”到什么程度是可以接受的,不可再分。
分治思想(divide-and-conquer)是一种简单朴素的思想,很多问题都可以这样解决。ForkJoin就相当于分治法的并行版本。 分治本身只是解决问题的思想,既可以顺序执行也可以并行执行,但是在并行环境中更加有效,因为可以并行处理子问题。而在并行方面,可并行处理问题要么是彼此完全独立的问题,要么是可分解单独处理的问题。可伸缩性又和能否并行处理紧密相关,因为如果不能并行处理就要受到单机处理能力的限制,也就难以伸缩了。
这个框架基于以下两种操作:
fork操作:当你把任务分成更小的任务和使用这个框架执行它们。
join操作:当一个任务等待它创建的任务的结束。
Fork/Join框架的核心是由以下两个类:
ForkJoinPool:它实现ExecutorService接口和work-stealing算法。它管理工作线程和提供关于任务的状态和它们执行的信息。
ForkJoinTask: 它是将在ForkJoinPool中执行的任务的基类。它提供在任务中执行fork()和join()操作的机制,并且这两个方法控制任务的状态。通常, 为了实现你的Fork/Join任务,你将实现两个子类的子类的类:RecursiveAction对于没有返回结果的任务和RecursiveTask 对于返回结果的任务。
使用fork/join,首先要创建fork/join任务,可以通过继承RecursiveAction或RecursiveTask来实现(ForkJoinTask是它们的父类)
RecursiveAction 不返回结果
RecursiveTask 返回结果
常用方法
compute(); 计算方法(分拆的子任务)
fork(); // 执行子任务
join(); // 子任务结束后返回对应结果
ForkJoinPool
除此之外,java还提供了个ForkJoinPool的工具类,它实现了工作窃取算法,使得空闲线程能够主动分担从别的线程分解出来的子任务,从而让所有的线程都尽可能处于饱满的工作状态,提高执行效率。
常用方法
execute(); //异步执行命令
invoke()和invokeAll(); // 异步执行命令,并返回对应结果
submit(); //异步执行命令,同时返回Future对象