Подтвердить что ты не робот

В Java, каковы преимущества потоков по циклам?

Меня спросили об этом на собеседовании, и я не уверен, что дал лучший ответ. Я упомянул, что вы можете выполнять параллельный поиск, а нулевые значения обрабатывались некоторыми способами, которые я не мог вспомнить. Теперь я понимаю, что думал о Optionals. Что мне здесь не хватает? Они утверждают, что это лучший или более сжатый код, но я не уверен, что согласен.


Если они задают этот вопрос на собеседовании и, очевидно, что это такое, то какая цель может его разрушить, кроме как затруднить поиск ответа? Я имею в виду, что вы ищете? Я мог бы сломать вопрос и ответить на все вопросы, но потом создать родительский вопрос со ссылками на все подзапросы... кажется довольно глупым. Пока мы на нем, пожалуйста, дайте мне пример менее широкого вопроса. Я не знаю, как просить только часть этого вопроса и до сих пор получаю осмысленный ответ. Я мог бы задать точно такой же вопрос по-другому. Например, я мог бы спросить: "Какую цель выполняют потоки?" или "Когда я буду использовать поток вместо цикла for?" или "Зачем беспокоиться о потоках, а не о циклах?" Однако все это один и тот же вопрос.

... или считается слишком широким, потому что кто-то дал очень длинный многоточечный ответ? Честно говоря, любой, кто знает, может сделать это практически с любым вопросом. Например, если вы, например, один из авторов JVM, вы могли бы говорить о циклах целый день, когда большинство из нас не могло.

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

Как отмечалось ниже, был дан адекватный ответ, который доказывает, что существует одно и что его достаточно просто предоставить.

4b9b3361

Ответ 1

Интересно, что вопрос о собеседовании спрашивает о преимуществах, не спрашивая о недостатках, поскольку есть и то, и другое.

Потоки - более декларативный стиль. Или более выразительный стиль. Можно считать, что лучше заявить о своем намерении в коде, чем описывать, как это делается:

 return people
     .filter( p -> p.age() < 19)
     .collect(toList());

... довольно ясно говорит о том, что вы фильтруете соответствующие элементы из списка, тогда как:

 List<Person> filtered = new ArrayList<>();
 for(Person p : people) {
     if(p.age() < 19) {
         filtered.add(p);
     }
 }
 return filtered;

Говорит "Я делаю петлю". Цель цикла заглубляется глубже в логике.

Потоки часто . Этот же пример показывает это. Терсер не всегда лучше, но если вы можете быть кратким и выразительным в одно и то же время, тем лучше.

Потоки имеют сильное сходство с функциями. Java 8 вводит lambdas и функциональные интерфейсы, которые открывают целую игрушку с мощными технологиями. Потоки обеспечивают наиболее удобный и естественный способ применения функций к последовательностям объектов.

Потоки поощряют меньшую изменчивость. Это связано с аспектом функционального программирования - тип программ, которые вы пишете с использованием потоков, как правило, является типом программ, в которых вы не изменяете объекты.

Потоки стимулируют ослабление связи. Код управления потоком не обязательно должен знать источник потока или его возможный метод завершения.

Потоки могут кратко выразить довольно сложное поведение. Например:

 stream.filter(myfilter).findFirst();

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

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

Но масштабы потоков. Помимо встроенной поддержки Java для параллельных потоков, существует несколько библиотек для распределенного масштабирования карты с использованием Streams в качестве API, потому что модель подходит.

Недостатки?

Производительность: цикл A for через массив чрезвычайно легкий как с точки зрения кучи, так и использования ЦП. Если необработанная скорость и аккуратность памяти являются приоритетом, использование потока хуже.

Знакомство. В мире полно опытных программистов, со многих языков, для которых знакомы петли, а потоки - новые. В некоторых средах вы хотите написать код, знакомый этому человеку.

Когнитивные накладные расходы. Из-за его декларативного характера и увеличения абстракции от того, что происходит под ним, вам может понадобиться создать новую ментальную модель того, как код относится к исполнению. На самом деле вам нужно делать это только тогда, когда все идет не так, или если вам нужно глубоко анализировать производительность или тонкие ошибки. Когда он "просто работает", он просто работает.

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

Ответ 2

  • Вы неправильно поняли: для параллельных операций используйте Stream s, а не Optional s.

  • Вы можете определять методы, работающие с потоками: принимать их как параметры, возвращать их и т.д. Вы не можете определить метод, который принимает цикл как параметр. Это позволяет выполнить сложную операцию потока один раз и использовать его много раз. Обратите внимание, что Java имеет здесь недостаток: ваши методы должны быть вызваны как someMethod(stream), а не stream own stream.someMethod(), поэтому их смешивание усложняет чтение: попробуйте просмотреть порядок операций в

    myMethod2(myMethod(stream.transform(...)).filter(...))
    

    Многие другие языки (С#, Kotlin, Scala и т.д.) допускают некоторую форму "методов расширения".

  • Даже если вам нужны только последовательные операции и вы не хотите их повторно использовать, чтобы вы могли использовать потоки или циклы, простые операции с потоками могут соответствовать довольно сложным изменениям в циклах.

Ответ 3

Синтаксическая забава в стороне, потоки предназначены для работы с потенциально бесконечно большими наборами данных, тогда как массивы, коллекции и почти каждый класс Java SE, который реализует Iterable, полностью находятся в памяти.

Недостатком Stream является то, что фильтры, сопоставления и т.д. не могут выдавать проверенные исключения. Это делает поток слабым выбором, например, для промежуточных операций ввода-вывода.

Ответ 4

Вы перебираете последовательность (массив, коллекцию, ввод,...), потому что вы хотите применить некоторую функцию к элементам последовательности.

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

Поэтому, учитывая некоторую циклическую задачу, в большинстве случаев вы можете выразить ее с меньшим количеством кода с использованием Streams, т.е. вы получите удобочитаемость.

Ответ 5

Я бы сказал, что его распараллеливание настолько прост в использовании. Попробуйте повторить миллионы записей параллельно с циклом for. Мы переходим ко множеству cpus, а не быстрее; так что чем проще будет работать параллельно, тем лучше, а с Stream это легкий ветерок.

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