fork / join框架比线程池更好吗?
使用新的fork /
join框架有什么好处,而不是仅在开始时将大任务简单地拆分为N个子任务,然后将它们发送到缓存的线程池(来自Executors),然后等待每个任务完成?我看不到使用fork
/ join抽象如何简化问题或使解决方案比我们多年以来的效率更高。
例如,本教程示例中的并行化模糊算法可以这样实现:
public class Blur implements Runnable { private int[] mSource;
private int mStart;
private int mLength;
private int[] mDestination;
private int mBlurWidth = 15; // Processing window size, should be odd.
public ForkBlur(int[] src, int start, int length, int[] dst) {
mSource = src;
mStart = start;
mLength = length;
mDestination = dst;
}
public void run() {
computeDirectly();
}
protected void computeDirectly() {
// As in the example, omitted for brevity
}
}
首先拆分,然后将任务发送到线程池:
// source image pixels are in src// destination image pixels are in dst
// threadPool is a (cached) thread pool
int maxSize = 100000; // analogous to F-J's "sThreshold"
List<Future> futures = new ArrayList<Future>();
// Send stuff to thread pool:
for (int i = 0; i < src.length; i+= maxSize) {
int size = Math.min(maxSize, src.length - i);
ForkBlur task = new ForkBlur(src, i, size, dst);
Future f = threadPool.submit(task);
futures.add(f);
}
// Wait for all sent tasks to complete:
for (Future future : futures) {
future.get();
}
// Done!
任务进入线程池的队列,当工作线程可用时,从队列中执行任务。只要拆分足够精细(避免特别地等待最后一个任务)并且线程池具有足够的线程(至少N个处理器)线程,则所有处理器都将全速工作,直到完成整个计算为止。
我想念什么吗?使用fork / join框架的附加价值是什么?
回答:
我认为基本的误解是,Fork / Join示例 显示出 工作,而只是显示了某种标准的分而治之。
偷工作可能是这样的:工人B已经完成工作。他是一个善良的人,所以他环顾四周,发现工人A仍在努力工作。他走过去问:“嘿,伙计,我可以帮你。”
一个答复。“很酷,我要完成1000个单位的任务。到目前为止,我已经完成了345个工作,剩下655个工作。请把673改为1000,我将把346改为672。”
B说:“好,让我们开始吧,我们可以早些去酒吧。”
您会看到-工人即使在开始实际工作时也必须彼此沟通。这是示例中缺少的部分。
另一方面,这些示例仅显示类似“使用分包商”的内容:
工人A:“党,我有1000个工作单元。对我来说太多了。我自己做500个工作,然后将500个工作分包给别人。”
直到大任务分解成每个10个单位的小包为止。这些将由可用的工人执行。但是,如果一个小药包是一种毒药,并且比其他小药包需要更长的时间-倒霉,分裂阶段就结束了。
Fork /
Join与预先拆分任务之间唯一的区别是:当预先拆分时,您从一开始就拥有完整的工作队列。示例:1000个单位,阈值为10,因此队列中有100个条目。这些数据包分配给线程池成员。
Fork / Join比较复杂,它试图使队列中的数据包数量减少:
- 步骤1:将一个包含(1 … 1000)的数据包放入队列
- 步骤2:一名工作人员弹出数据包(1 … 1000),并用两个数据包替换:(1 … 500)和(501 … 1000)。
- 步骤3:一名工作人员弹出数据包(500 … 1000)并推送(500 … 750)和(751 … 1000)。
- 步骤n:堆栈包含以下数据包:(1..500),(500 … 750),(750 … 875)…(991..1000)
- 步骤n + 1:弹出并执行数据包(991..1000)
- 步骤n + 2:数据包(981..990)弹出并执行
- 步骤n + 3:弹出数据包(961..980),并将其拆分为(961 … 970)和(971..980)。....
您会看到:在Fork / Join中,队列较小(示例中为6),并且“ split”和“ work”阶段是交错的。
当多个工作人员同时弹出并推动时,交互作用当然不是很清楚。
以上是 fork / join框架比线程池更好吗? 的全部内容, 来源链接: utcz.com/qa/425940.html