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

回到顶部