Java 7:分叉/连接框架

发布于 2024-09-15 07:43:38 字数 30 浏览 7 评论 0原文

有人能解释一下什么是 Fork/Join 吗?

Can someone explain what Fork/Join is?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

懒的傷心 2024-09-22 07:43:38

Fork Join 是一个新框架,具有更易于使用的并行、分而治之算法的 API。

假设您有一个长时间运行的任务,在本例中,它有一个复杂的算法。您可能想要分叉大型任务,然后现在处理这两项任务。现在假设这两个任务仍然太大,您可以将每个任务分成两个任务(此时有四个任务)。

您将继续此操作,直到每个任务都达到可接受的大小并调用该算法。重要的是要知道每个任务的调用是并行完成的。当任务完成时,它会与它所分叉的其他任务合并并合并结果。

这将持续下去,直到所有任务都已加入并返回一个任务。

Fork Join is a new framework that has an easier to use API for a parallel, divide and conquer algorithm.

Say you have a long running task that, for this instance, has a complicated algorithm. You would want to fork the large tasks and now work on those two tasks. Now lets say that that those two tasks are still too big, you would fork each into two tasks (at this point there are four).

You would continue this until each task is at an acceptable size and invoke the algorithm. It is important to know the invocation of each task is done in parallel. When the task is completed it is joined with the other task it was forked with and consolidate the results.

This will continue until all tasks have been joined and one task is returned.

谁对谁错谁最难过 2024-09-22 07:43:38

除了已经说过的之外,fork/join 还利用工作窃取 - 没有事情可做的线程可以从仍然忙碌的其他线程窃取任务。下面是一个可以帮助您了解如何使用 FJ 的示例:

public class SumCounter extends RecursiveTask<Long> { 

  private final Node node; 

  public SumCounter(Node node) { 
    this.node = node; 
  } 

  @Override
  protected Long compute() { 
    long sum = node.getValue();
    List<ValueSumCounter> subTasks = new LinkedList<>(); 

    for(Node child : node.getChildren()) { 
      SumCounter task = new SumCounter(child); 
      task.fork(); // run asynchronously
      subTasks.add(task); 
    }

    for(SumCounter task : subTasks) { 
      sum += task.join(); // wait for the result 
    } 

    return sum;
  }

  public static void main(String[] args) { 
    Node root = getRootNode(); 
    new ForkJoinPool().invoke(new SumCounter(root)); 
  }

}

In addition to what was already said, fork/join utilizes work stealing - threads that run out of things to do can steal tasks from other threads that are still busy. And here is an example that can help you to understand how FJ can be used:

public class SumCounter extends RecursiveTask<Long> { 

  private final Node node; 

  public SumCounter(Node node) { 
    this.node = node; 
  } 

  @Override
  protected Long compute() { 
    long sum = node.getValue();
    List<ValueSumCounter> subTasks = new LinkedList<>(); 

    for(Node child : node.getChildren()) { 
      SumCounter task = new SumCounter(child); 
      task.fork(); // run asynchronously
      subTasks.add(task); 
    }

    for(SumCounter task : subTasks) { 
      sum += task.join(); // wait for the result 
    } 

    return sum;
  }

  public static void main(String[] args) { 
    Node root = getRootNode(); 
    new ForkJoinPool().invoke(new SumCounter(root)); 
  }

}
梦行七里 2024-09-22 07:43:38

假设您有一组需要处理的事物。您有许多线程可以获取该集合的子集并处理它们。他们都同时执行此操作(分叉部分),然后等待最后一个完成(连接部分),然后再返回。

Say you have a collection of things that need to be processed. You have a number of threads that can grab subsets of this collection and process them. They all do this concurrently (the fork part) then wait on the last one to finish (the join part) before returning.

夜声 2024-09-22 07:43:38

我来回答一下什么是Fork Join并行。这是许多系统中广泛用于实现并发的并行设计模式之一。我将用一个例子来解释这个设计模式。

例如,假设我们有执行任务序列的程序:

A -> B-> C-> D. 这里A、B、C、D 是任务。

  • A 需要 8 秒
  • B 需要 4 秒
  • C 需要 6 秒
  • D 需要 7 秒

因此,该程序执行总共需要 8+4+6+7 = 25 秒。

现在您发现任务 A、B、C 是独立的,而 D 取决于 A、B、C 任务的结果。现在您可能会感觉到,我们可以同时开始执行 B,而不是等待 A 完成。任务 C 相同
可以与A和B同时启动任务。你可以做的是:你可以在主线程中调用3个新线程,并为它们分配A、B、C任务,并等待结果,然后开始执行任务D。如果你的机器有多个核心,那么这些线程可以并行运行。

现在程序的执行时间为:

max(time_taken_A,_B,_C) + time_taken_D + threading_overhead_time

,几乎等于 = 8 + 7 + k = 15 + k;

在 fork join 并行中,只有当这些任务是独立的时,我们才可以使用新线程卸载这些任务。否则我们将面临竞争条件。如果您有一个程序,其中一个任务正在等待另一任务执行,但这不依赖于其结果,那么您可以使用 fork join 并行性使用新线程卸载这两个任务,并且可以获得性能提升。但始终要考虑头顶上的线程。如果您的任务重量非常轻,那么使用这些并行模式会因为线程创建、上下文切换开销而降低性能。

I will answer what is Fork Join parallelism. This is one of the parallel design pattern widely used in many systems to achieve concurrency. I will explain this design pattern using a example.

For example lets say we have program which executes sequence of tasks :

A -> B -> C -> D. Here A,B,C,D are tasks.

  • A takes 8 seconds
  • B takes 4 seconds
  • C takes 6 seconds
  • D takes 7 seconds

So it will take total of 8+4+6+7 = 25 seconds for this program execution.

Now you found out that tasks A,B,C are independent and D is depend on A,B,C tasks' results. Now you may get a feeling that instead of waiting for A to finish we can start the execution of B simultaneously. Same for Task C
can start the task simultaneously with A and B. What you can do is: You can invoke 3 new threads by your main thread and assign them A,B,C tasks and wait for the results before start the execution of task D. If your machine has multiple cores then these threads can run in parallel.

Now the execution time taken for the program is :

max(time_taken_A,_B,_C) + time_taken_D + threading_overhead_time

which is almost equal to = 8 + 7 + k = 15 + k;

In fork join parallelism we can offload tasks with a new thread only if these tasks are independent. Other wise we will face race conditions. If you have a program where one task is waiting for another task execution but this is not dependent on its results then you can offload these two tasks with new threads using fork join parallelism and you can get performance boost. But always think about the threading over head. If your tasks are very light weighted then using these parallel patterns will decrease your performance because of the thread creation, context switching overheads.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文