2014-12-26 2 views
1

В соответствии с этим article есть некоторые серьезные недостатки с архитектурой Fork-Join в Java. По моему пониманию Streams в Java 8 используют внутреннюю структуру Fork-Join. Мы можем легко превратить поток в параллель с помощью метода parallel(). Но когда мы отправляем многолетнюю задачу параллельному потоку, он блокирует все потоки в пуле, проверяем this. Такое поведение неприемлемо для приложений реального мира.Проблемы с потоками в Java 8

Мой вопрос, каковы различные соображения, которые следует принимать во внимание, прежде чем использовать эти конструкции в высокопроизводительных приложений (например, анализ собственного капитала, фондовый рынок тикер и т.д.)

+2

Я не уверен, что автор этой статьи совершенно непредвзято. Посмотрите, на кого он работает, и что они делают. Я не говорю, что он ошибается или нечестен, но он/она предлагает продукт, который, похоже, конкурирует с стандартной платформой fork-join Oracle. Прочитайте, что он говорит о «серьезных недостатках» с этим. –

+0

@ Stephen Если вы хотите обратиться ко мне напрямую, я бы дал вам длинную историю того, откуда пришли статьи. Продукты с открытым исходным кодом, которые я поддерживаю, возвращаются на 30 лет. – edharned

+0

@edharned Я переношу свой проект на Java 8 и планирую использовать Streams. Это критическое приложение, связанное с фондовым рынком, которое выполняет множество вычислений в разумные сроки. Но Streams использует только инфраструктуру FJ, так какие же пункты следует заботиться, прежде чем использовать их? –

ответ

2

соображения похожи на другие виды использования несколько потоков.

  • Используйте только несколько потоков, если вы знаете, что они помогают. Цель состоит не в том, чтобы использовать каждое ваше ядро, а для того, чтобы иметь программу, которая соответствует вашим требованиям.
  • Не забывайте, что многопоточность поставляется с накладными расходами, и эти накладные расходы могут превышать ценность, которую вы получаете.
  • Многопоточность может иметь большие выбросы. Когда вы проверяете производительность, вы должны не только смотреть на пропускную способность (что должно быть лучше), но и на распределение ваших задержек (что часто бывает хуже в крайних случаях)
  • Для низкой латентности переключение между потоками как можно меньше. Если вы можете сделать все в одном потоке, это может быть хорошим вариантом.
  • Для низкой латентности вы не хотите играть хорошо, вместо этого вы хотите свести к минимуму дрожание, выполняя такие действия, как привязка занятых ожидающих потоков к изолированным ядрам. Чем больше изолированных ядер, тем меньше нежелательных ядер, вы должны запускать такие вещи, как пулы потоков.
+0

Питер, Спасибо за ваш ответ. Я знаю эти соображения, но моя настоящая забота - об использовании Streams специально. Потоки - отличный инструмент и наряду с лямбда-выражениями могут быть действительно полезными. Но они, похоже, используют внутреннюю структуру Fork-Join и могут иметь серьезные проблемы в реальных приложениях. Я хочу знать, какие проблемы мне нужно знать, прежде чем использовать их в рабочей среде. –

+3

@ahil_mittal не предполагают, что это легко и выгодно размещать повсюду. Вместо этого предположите, что, если вы не проверили эту параллель, это, вероятно, больше проблем, чем того стоит. –

+0

Я понял, что не рекомендуется использовать параллельные потоки до тех пор, пока мы не получим некоторые реальные преимущества. Но даже если мы используем регулярные потоки (последовательные), они будут использовать только фреймворк FJ. Согласно опубликованной ссылке, она может быть вредной для критически важных приложений, выполняющих множество вычислительных работ. –

1

API потоков делает параллелизм обманчиво простым. Как уже указывалось ранее, необходимо ли тщательно анализировать и тестировать использование параллельного потока для ускорения вашего приложения в реальном контексте выполнения. Мой собственный опыт работы с параллельными потоками потоков предлагает следующее (и я уверен, что этот список далеко не полный):

  • Стоимость операций, выполняемых на элементах потока по сравнению стоимости parallelising машин определяет потенциальное преимущество параллельных потоков. Например, найти максимум в массиве двойников настолько быстро, используя жесткий цикл, что потоки накладных расходов никогда не стоят. Как только операции становятся более дорогими, баланс начинает подсказывать в пользу API параллельных потоков - в идеальных условиях, скажем, многоядерном компьютере, посвященном одному алгоритму). Я призываю вас экспериментировать.

  • Вам необходимо иметь время и выносливость, чтобы изучить внутренность API потока. Есть неожиданные подводные камни. Например, Spliterator может быть построен из обычного итератора в простой инструкции. Под капотом элементы, созданные итератором, сначала собираются в массив. В зависимости от количества элементов, создаваемых Итератором, этот подход становится очень или даже слишком ресурсным.

  • В приведенной статье показано, что мы полностью во власти Oracle, это не совсем так. Вы можете написать собственный Spliterator, который разбивает входные данные на куски, специфичные для вашей ситуации, вместо того, чтобы полагаться на реализацию по умолчанию. Или вы можете написать свой собственный ThreadFactory (см. Метод ForkJoinPool.makeCommonPool).

  • Вы должны быть осторожны, чтобы не создавать взаимоблокировки.Если задачи, выполняемые на элементах потока, используют сам ForkJoinPool, может возникнуть взаимоблокировка. Вам нужно научиться использовать API ForkJoinPool.ManagedBlocker и его использование (что я считаю скорее противоположным, чем легко понять). Технически вы сообщаете ForkJoinPool, что поток блокируется, что может привести к созданию дополнительных потоков, чтобы сохранить степень параллелизма неповрежденной. Конечно, создание дополнительных потоков не является бесплатным.

Просто мои пять центов ...

+0

Вы также можете прочитать это другое сообщение на SO: http://stackoverflow.com/questions/20375176/should-i-always-use-a-parallel-stream-when-possible/20384377#20384377 – edharned

+0

Спасибо за Справка. Я провел обширные тесты производительности параллельных потоков, и я могу только согласиться с тем, что там сказано. –

1

Точка (есть на самом деле 17) статей, чтобы указать на то, что F/J Framework больше исследовательского проекта, чем общего назначения разработка коммерческих приложений.

Критикуйте объект, а не мужчину. Попытка сделать это сложнее, когда основная проблема с каркасом заключается в том, что архитектор является профессором/ученым, а не инженером/коммерческим разработчиком. Консолидация PDF, загружаемая из этой статьи, в большей степени связана с проблемой использования исследовательских стандартов, а не технических стандартов.

Параллельные потоки работают нормально, пока вы не попытаетесь их масштабировать. Рамка использует технологию pull; запрос переходит в очередь отправки, поток должен вытащить запрос из очереди отправки. Задача возвращается в дефис нисходящей нити, другие потоки должны вытаскивать Task из deque. Этот метод не очень хорошо масштабируется. В технологии push каждая задача разбивается на каждый поток в системе. Это работает намного лучше в крупномасштабных средах.

Есть много других проблем с масштабированием, поскольку даже Павел Сандос из Oracle указал: Например, если у вас есть 32 ядра и они выполняют Stream.of (s1, s2, s3, s4) .flatMap (x -> x) .reduce (...), то в лучшем случае вы будете использовать только 4 ядра. В статье указывается, что с загружаемым программным обеспечением масштабирование не работает, и parquential technique необходим, чтобы избежать переполнения стека и OOME.

Использование параллельных потоков. Но остерегайтесь ограничений.

Смежные вопросы