Zoeken…


Fork / Join-taken in Java

Het vork / join-framework in Java is ideaal voor een probleem dat in kleinere stukken kan worden verdeeld en parallel kan worden opgelost. De fundamentele stappen van een vork / join-probleem zijn:

  • Verdeel het probleem in meerdere stukken
  • Los elk van de stukjes parallel aan elkaar op
  • Combineer elk van de suboplossingen in één totaaloplossing

Een ForkJoinTask is de interface die een dergelijk probleem definieert. Algemeen wordt verwacht dat u een van de abstracte implementaties ervan (meestal de RecursiveTask ) in een subklasse onderbrengt in plaats van de interface rechtstreeks te implementeren.

In dit voorbeeld gaan we een verzameling gehele getallen optellen, delen totdat we batchgroottes van niet meer dan tien bereiken.

import java.util.List;
import java.util.concurrent.RecursiveTask;

public class SummingTask extends RecursiveTask<Integer> {
    private static final int MAX_BATCH_SIZE = 10;

    private final List<Integer> numbers;
    private final int minInclusive, maxExclusive;

    public SummingTask(List<Integer> numbers) {
        this(numbers, 0, numbers.size());
    }

    // This constructor is only used internally as part of the dividing process
    private SummingTask(List<Integer> numbers, int minInclusive, int maxExclusive) {
        this.numbers = numbers;
        this.minInclusive = minInclusive;
        this.maxExclusive = maxExclusive;
    }

    @Override
    public Integer compute() {
        if (maxExclusive - minInclusive > MAX_BATCH_SIZE) {
            // This is too big for a single batch, so we shall divide into two tasks
            int mid = (minInclusive + maxExclusive) / 2;
            SummingTask leftTask = new SummingTask(numbers, minInclusive, mid);
            SummingTask rightTask = new SummingTask(numbers, mid, maxExclusive);

            // Submit the left hand task as a new task to the same ForkJoinPool
            leftTask.fork();

            // Run the right hand task on the same thread and get the result
            int rightResult = rightTask.compute();

            // Wait for the left hand task to complete and get its result
            int leftResult = leftTask.join();

            // And combine the result
            return leftResult + rightResult;
        } else {
            // This is fine for a single batch, so we will run it here and now
            int sum = 0;
            for (int i = minInclusive; i < maxExclusive; i++) {
                sum += numbers.get(i);
            }
            return sum;
        }
    }
}

Een exemplaar van deze taak kan nu worden doorgegeven aan een exemplaar van ForkJoinPool .

// Because I am not specifying the number of threads
// it will create a thread for each available processor
ForkJoinPool pool = new ForkJoinPool();

// Submit the task to the pool, and get what is effectively the Future
ForkJoinTask<Integer> task = pool.submit(new SummingTask(numbers));

// Wait for the result
int result = task.join();


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow