Чем фреймворк fork / join лучше, чем пул потоков? - PullRequest
123 голосов
/ 28 октября 2011

Каковы преимущества использования новой платформы 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?

Ответы [ 11 ]

1 голос
/ 24 июня 2019

Я хотел бы добавить короткий ответ для тех, у кого мало времени, чтобы читать длинные ответы.Сравнение взято из книги Applied Akka Patterns:

Ваше решение относительно того, использовать ли fork-join-executor или thread-executor, во многом зависит от того, выполняются ли операции в этом диспетчеребудет блокировка.Aork-join-executor дает вам максимальное количество активных потоков, тогда как thread-pool-executor дает вам фиксированное количество потоков.Если потоки заблокированы, fork-join-executor создаст больше, а thread-pool-executor - нет.Для блокирующих операций вам, как правило, лучше работать с пулом потоков-исполнителем, потому что он предотвращает взрыв ваших потоков.Более «реактивные» операции лучше выполнять в fork-join-executor.

...