Чи спостерігаються потоки Java 8, схожі на RxJava?
Визначення потоку Java 8:
Класи в новому
java.util.stream
пакеті забезпечують API Stream для підтримки операцій у функціональному стилі над потоками елементів.
Чи спостерігаються потоки Java 8, схожі на RxJava?
Визначення потоку Java 8:
Класи в новому
java.util.stream
пакеті забезпечують API Stream для підтримки операцій у функціональному стилі над потоками елементів.
Відповіді:
TL; DR : Усі послідовності / потокові версії для обробки потоків пропонують дуже подібний API для побудови трубопроводу. Відмінності полягають у API для обробки багатопотокової рідини та складу трубопроводів.
RxJava сильно відрізняється від Stream. З усіх речей JDK, найбільш близьким до rx.Observable є, мабуть, комбінація java.util.stream.Collector Stream + CompletableFuture (що коштує за рахунок вирішення додаткового рівня монади, тобто для обробки конверсії між Stream<CompletableFuture<T>>
та CompletableFuture<Stream<T>>
).
Існують значні відмінності між спостережуваним та потоковим:
Stream#parallel()
розбиває послідовність на розділи, Observable#subscribeOn()
а Observable#observeOn()
не; важко емулювати Stream#parallel()
поведінку за допомогою Observable, у неї колись був .parallel()
метод, але цей метод викликав стільки плутанини, що .parallel()
підтримка була перенесена в окремий сховище на github, RxJavaParallel. Більше деталей - в іншій відповіді .Stream#parallel()
не дозволяє вказати пул потоків для використання, на відміну від більшості методів RxJava, що приймають необов'язковий Scheduler. Оскільки всі екземпляри потоку в JVM використовують один і той же пул fork-join, додавання .parallel()
може випадково вплинути на поведінку в іншому модулі вашої програмиObservable#interval()
, Observable#window()
і багато інших; Це здебільшого тому, що потоки засновані на тязі, а висхідний потік не контролює, коли слід випускати наступний елемент за течієюtakeWhile()
, takeUntil()
); Обхід використання Stream#anyMatch()
обмежений: це термінальна робота, тому ви не можете використовувати її більше одного разу в потоціObservable#using()
); ви можете обернути потік IO або mutex з ним і бути впевненим, що користувач не забуде звільнити ресурс - він буде розміщений автоматично після припинення підписки; У потоці є onClose(Runnable)
метод, але вам доведеться викликати його вручну або за допомогою пробних ресурсів. E. g. ви повинні мати на увазі, що файли № рядків () повинні бути укладені у блок "пробні ресурси".Раунд: RxJava значно відрізняється від потоків. Справжніми альтернативами RxJava є інші реалізації ReactiveStreams , наприклад відповідна частина Akka.
Оновлення . Існує хитрість використання пулу fork-join за замовчуванням для Stream#parallel
, див. Спеціальний пул потоків у паралельному потоці Java 8
Оновлення . Все вищезазначене базується на досвіді роботи з RxJava 1.x. Тепер, коли RxJava 2.x тут , ця відповідь може бути застарілою.
Stream.generate()
та пройти власну Supplier<U>
реалізацію, лише один простий метод, з якого ви надаєте наступний елемент у потоці. Існують навантаження інших методів. Щоб легко побудувати послідовність, Stream
яка залежить від попередніх значень, ви можете використовувати interate()
метод, кожен Collection
має stream()
метод і Stream.of()
будує a Stream
з varargs або масиву. Нарешті, StreamSupport
є підтримка більш просунутого створення потоку за допомогою сплітераторів або для примітивних типів потоків.
takeWhile()
, takeUntil()
);" - Я вважаю, що в JDK9 є takeWhile () і dropWhile ()
Java 8 Stream і RxJava виглядає досить схоже. Вони мають схожих операторів (фільтр, карта, flatMap ...), але не створені для того ж використання.
Ви можете виконувати завдання асинхону за допомогою RxJava.
За допомогою потоку Java 8 ви будете переміщувати предмети колекції.
Ви можете зробити те саме, що і в RxJava (прохідні елементи колекції), але, оскільки RxJava зосереджена на одночасному завданні, ..., він використовує синхронізацію, засувку, ... Отже, те саме завдання, що використовує RxJava, може бути повільніше, ніж з потоком Java 8.
RxJava можна порівняти CompletableFuture
, але це може обчислити більше ніж одне значення.
parallelStream
підтримує аналогічну синхронізацію простих обходів / карт / фільтрування тощо.
Існує кілька технічних та концептуальних відмінностей, наприклад, потоки Java 8 - це одноразове використання, синхронна послідовність значень на основі витягу, тоді як спостережувані RxJava є повторно спостережуваними, адаптивно заснованими на натисканні, потенційно асинхронними послідовностями значень. RxJava орієнтований на Java 6+ та працює і на Android.
Потоки Java 8 базуються на основі потягу. Ви повторюєте потік Java 8, що споживає кожен елемент. І це може бути нескінченний потік.
RXJava Observable
за замовчуванням заснований на push. Ви підписалися на спостережуване, і ви отримаєте сповіщення, коли наступний елемент прибуде ( onNext
), або коли потік завершено ( onCompleted
), або коли сталася помилка ( onError
). Тому що з Observable
ви отримуєте onNext
, onCompleted
, onError
події, ви можете зробити деякі потужні функції , такі як об'єднання різних Observable
сек на новий ( zip
, merge
, concat
). Інші речі, які ви можете зробити, це кешування, дроселювання, ... І він використовує більш-менш один і той же API на різних мовах (RxJava, RX в C #, RxJS, ...)
За замовчуванням RxJava є однопотоковою. Якщо ви не почнете використовувати Планувальники, все відбуватиметься в одній темі.
Існуючі відповіді є вичерпними та правильними, але чіткого прикладу для початківців не вистачає. Дозвольте мені поставити деякі конкретні терміни, такі як "push / pull-based" та "re-opable". Примітка : я ненавиджу цей термін Observable
(це потік заради неба), тому просто посилаюся на потоки J8 проти RX.
Розглянемо список цілих чисел,
digits = [1,2,3,4,5]
Потік J8 - це утиліта для зміни колекції. Наприклад, навіть цифри можуть бути вилучені як,
evens = digits.stream().filter(x -> x%2).collect(Collectors.toList())
Це в основному карта Python , фільтрування, зменшення , дуже приємне (і давно прострочене) додаток до Java. Але що робити, якщо цифри не були зібрані достроково - а якщо цифри надходили в поточний час під час роботи програми - ми могли б відфільтрувати парні дані в реальному часі.
Уявіть, що окремий процес потоку виводить цілі числа у випадкові години, коли програма працює ( ---
позначає час)
digits = 12345---6------7--8--9-10--------11--12
У RX even
може реагувати на кожну нову цифру і застосовувати фільтр в режимі реального часу
even = -2-4-----6---------8----10------------12
Не потрібно зберігати вхідні та вихідні списки. Якщо ви хочете вивести список, не існує проблеми, яка також є поточною. Насправді все - це потік.
evens_stored = even.collect()
Ось чому такі терміни, як "стан без громадянства" та "функціонал" більше асоціюються з RX
RxJava також тісно пов'язаний з ініціативою реактивних потоків і розглядає його як просту реалізацію API реактивних потоків (наприклад, порівняно з реалізацією потоків Akka ). Основна відмінність полягає в тому, що реактивні потоки розроблені так, щоб вони могли справляти тиск проти, але якщо ви подивитеся на сторінку реактивних потоків, ви отримаєте ідею. Вони досить добре описують свої цілі, і потоки також тісно пов'язані з реактивним маніфестом .
Потоки Java 8 в значній мірі є реалізацією безмежної колекції, дуже схожою на Scala Stream або Clozyre Lezy seq .
Потоки Java 8 дозволяють ефективно обробляти дійсно великі колекції, використовуючи багатоядерні архітектури. На відміну від цього, RxJava є однопоточним за замовчуванням (без Планувальників). Тож RxJava не скористається багатоядерними машинами, якщо ви самі не кодуєте цю логіку.