简体   繁体   中英

Java 7: Fork/Join Framework

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

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.

this is a very good resource to understand Fork and Join :

Fork and Join: Java Can Excel at Painless Parallel Programming Too! By Julien Ponge

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)); 
  }

}

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.

Let me just put my two cents to make basic understanding of Fork/Join simple.

What is Fork/Join?

The fork/join framework is an implementation of the ExecutorService interface
that helps you take advantage of multiple processors. It is designed for work 
that can be broken into smaller pieces recursively. The goal is to use all the
available  processing power to enhance the performance of your application.
  • This framework is very useful for modeling divide-and-conquer problems. This approach is suitable for tasks that can be divided recursively and computed on a smaller scale; the computed results are then combined.
  • The framework is an implementation of the ExecutorService interface and provides an easy-to-use concurrent platform in order to exploit multiple processors.

Term useful for this framework

  • Forking : Dividing the task into smaller tasks is forking.
  • Joining : Merging the results from the smaller tasks is joining

As with any ExecutorService implementation, the fork/join framework distributes tasks to worker threads in a thread pool. The fork/join framework is distinct because it uses a work-stealing algorithm . Worker threads that run out of things to do can steal tasks from other threads that are still busy.

The Fork/Join algorithm is designed as follows:

  • split tasks
  • fork the tasks
  • join the tasks
  • compose the results
 doRecursiveTask(input){ if( task is small enough to handled by a thread){ compute the small task; if there is result to return, then do so }else{ divide the task ie, fork() into two parts call compute on first task, join on second task, combine both results and return } } 

What is work-stealing algorithm?

Each worker thread in the Fork/Join framework has a work queue, which is implemented using a Deque. Each time a new task (or subtask) is created, it is pushed to the head of its own queue. When a task completes a task and executes a join with another task that is not completed yet, it works smart. The thread pops a new task from the head of its queue and starts executing rather than sleeping (in order to wait for another task to complete). In fact, if the queue of a thread is empty, then the thread pops a task from the tail of the queue belonging to another thread. This is nothing but a work-stealing algorithm. More detail is here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM