Suche…


Gabel- / Join-Aufgaben in Java

Das Fork / Join-Framework in Java ist ideal für ein Problem, das in kleinere Teile aufgeteilt und parallel gelöst werden kann. Die grundlegenden Schritte eines Gabel / Join-Problems sind:

  • Teilen Sie das Problem in mehrere Teile
  • Löse die einzelnen Teile parallel zueinander
  • Kombinieren Sie jede der Unterlösungen zu einer Gesamtlösung

Eine ForkJoinTask ist die Schnittstelle, die ein solches Problem definiert. Es wird allgemein erwartet, dass Sie eine seiner abstrakten Implementierungen (normalerweise die RecursiveTask ) subclassieren, anstatt die Schnittstelle direkt zu implementieren.

In diesem Beispiel werden wir eine Sammlung von ganzen Zahlen zusammenfassen, die sich teilen, bis Chargengrößen von maximal zehn erreicht werden.

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

Eine Instanz dieser Aufgabe kann jetzt an eine Instanz von ForkJoinPool übergeben werden .

// 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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow