ForkJoinPool и Future.Get

Предполагая, что у меня есть настройка ForkJoinPool со степенью параллелизма n, и что я вызываю параллельные вычисления следующим образом:

 workpool.submit(
            () -> {
                    objects.values().parallelStream().forEach(obj -> {
                        obj.foo();
                    });
                });

Я делаю это для того, чтобы созданные там потоки создавались внутри рабочего пула (у меня есть разные компоненты системы, которые нужно изолировать). Теперь предположим, что поток, в котором это вызывается, также выполняется внутри этого рабочего пула, и я делаю:

 Future<?> wait =  workpool.submit(
            () -> {
                    objects.values().parallelStream().forEach(obj -> {
                        obj.foo();
                    });
                });
 wait.get()

1) Блокирую ли я поток в ForkJoinPool? Если бы я заблокировал все n потоков на фьючерсах при попытке запланировать задачу в рабочем пуле, привело бы это к взаимоблокировке? Мне не ясно, означает ли "максимальная степень параллелизма" в ForkJoinPool, что (при наличии n неблокированных задач) всегда будет выполняться n потоков, или существует фиксированное число потоков, независимо от того, есть заблокированы. Что, если я использую wait.join() вместоwait.join вместо этого (мне не нужны проверенные исключения, так как любое исключение, созданное в этом коде, уже будет генерировать исключение времени выполнения. Если я правильно понимаю, join() позволит потокам выполнять задачи в очереди во время ожидания)

2) Я все еще получаю преимущество от облегченных задач forkjoin параллельного потока, если я создаю исполняемый класс «оболочки», выполняя () -> {}

3) Есть ли какие-либо недостатки/преимущества в использовании этого вместо этого (при условии, что .join() действительно реализует поведение кражи работы, которое, как я думаю, оно делает):

        CompletableFuture.supplyAsync(this::mylambdafunction, workpool)  
             .thenAccept(this::mynextfunction);

person user1018513    schedule 06.04.2017    source источник


Ответы (1)


Ответ на пункт 1: трудно понять, будет ли ваш код блокироваться, не видя фактических реализаций методов. Одним из подходов к работе с блокирующим кодом является увеличение количества потоков в пуле потоков forkjoin. Обычно количество потоков в потоке forkjoin равно n+1 для задач с интенсивными вычислениями, где n=количество процессоров. Или, если у вас есть блокировка ввода-вывода, вы можете использовать ManagedBlocker.

Ответ на пункт 2: Да

Ответ по пункту 3: очевидным преимуществом вашего кода completableFuture является то, что thenAccept не блокирует. Таким образом, управление немедленно перейдет от вашего блока CompletableFuture к следующему оператору без ожидания, тогда как в более раннем коде, который вы написали с пулом ForkJoin, функция wait.get() будет блокироваться до тех пор, пока вы не получите ответ, и не будет продолжаться до тех пор.

person Avneet Paul    schedule 08.04.2017