Các luồng Java 8 có giống với các quan sát RxJava không?
Định nghĩa luồng Java 8:
Các lớp trong
java.util.stream
gói mới cung cấp API Stream để hỗ trợ các hoạt động theo kiểu chức năng trên các luồng phần tử.
Các luồng Java 8 có giống với các quan sát RxJava không?
Định nghĩa luồng Java 8:
Các lớp trong
java.util.stream
gói mới cung cấp API Stream để hỗ trợ các hoạt động theo kiểu chức năng trên các luồng phần tử.
Câu trả lời:
TL; DR : Tất cả các lib xử lý chuỗi / luồng đang cung cấp API rất giống nhau để xây dựng đường ống. Sự khác biệt là trong API để xử lý đa luồng và thành phần của đường ống.
RxJava khá khác so với Stream. Trong tất cả mọi thứ của JDK, gần nhất với rx.Observable có lẽ là java.util.stream.Collector Stream + CompleteableFuture (có chi phí xử lý lớp đơn lớp bổ sung, tức là phải xử lý chuyển đổi giữa Stream<CompletableFuture<T>>
và CompletableFuture<Stream<T>>
).
Có sự khác biệt đáng kể giữa Quan sát và Luồng:
Stream#parallel()
chia chuỗi thành các phân vùng, Observable#subscribeOn()
và Observable#observeOn()
không; Thật khó để mô phỏng Stream#parallel()
hành vi với Observable, nó đã từng có .parallel()
phương thức nhưng phương thức này gây ra nhiều nhầm lẫn đến mức .parallel()
hỗ trợ đã được chuyển sang kho lưu trữ riêng trên github, RxJavaParallel. Thêm chi tiết trong một câu trả lời khác .Stream#parallel()
không cho phép chỉ định nhóm luồng sử dụng, không giống như hầu hết các phương thức RxJava chấp nhận Bộ lập lịch tùy chọn. Do tất cả các phiên bản luồng trong JVM sử dụng cùng một nhóm kết nối ngã ba, việc thêm .parallel()
có thể vô tình ảnh hưởng đến hành vi trong một mô-đun khác của chương trình của bạnObservable#interval()
, Observable#window()
và nhiều hoạt động khác; điều này chủ yếu là do Luồng dựa trên kéo và ngược dòng không kiểm soát được khi nào phát ra phần tử tiếp theo xuôi dòngtakeWhile()
, takeUntil()
); cách sử dụng thay thế Stream#anyMatch()
bị hạn chế: đó là hoạt động của thiết bị đầu cuối, vì vậy bạn không thể sử dụng nhiều lần trên mỗi luồngObservable#using()
); bạn có thể gói luồng IO hoặc mutex với nó và chắc chắn rằng người dùng sẽ không quên giải phóng tài nguyên - nó sẽ được xử lý tự động khi chấm dứt đăng ký; Stream có onClose(Runnable)
phương thức, nhưng bạn phải gọi nó bằng tay hoặc thông qua try-with-resource. Ví dụ. bạn phải nhớ rằng Tập tin # dòng () phải được đặt trong khối tài nguyên thử.Làm tròn: RxJava khác với Luồng đáng kể. Các lựa chọn thay thế RxJava thực là các triển khai khác của ReactiveStreams , ví dụ như phần có liên quan của Akka.
Cập nhật . Có mẹo sử dụng nhóm kết nối ngã ba không mặc định cho Stream#parallel
, xem Nhóm luồng tùy chỉnh trong luồng song song Java 8
Cập nhật . Tất cả những điều trên được dựa trên trải nghiệm với RxJava 1.x. Bây giờ RxJava 2.x đã ở đây , câu trả lời này có thể đã lỗi thời.
Stream.generate()
và vượt qua Supplier<U>
triển khai của riêng bạn , chỉ một phương thức đơn giản mà bạn cung cấp mục tiếp theo trong luồng. Có vô số phương pháp khác. Để dễ dàng xây dựng một chuỗi Stream
phụ thuộc vào các giá trị trước đó, bạn có thể sử dụng interate()
phương thức, mỗi phương thức Collection
có một stream()
phương thức và Stream.of()
xây dựng một chuỗi Stream
từ một varargs hoặc mảng. Cuối cùng StreamSupport
có hỗ trợ cho việc tạo luồng nâng cao hơn bằng cách sử dụng bộ chia hoặc cho các kiểu nguyên thủy của luồng.
takeWhile()
, takeUntil()
);" - JDK9 có những thứ này, tôi tin rằng, trong TakeWhile () và dropWhile ()
Java 8 Stream và RxJava trông khá giống nhau. Chúng có các toán tử giống nhau (bộ lọc, bản đồ, bản đồ phẳng ...) nhưng không được xây dựng cho cùng một cách sử dụng.
Bạn có thể thực hiện các tác vụ asynchonus bằng RxJava.
Với luồng Java 8, bạn sẽ duyệt qua các mục trong bộ sưu tập của mình.
Bạn có thể thực hiện khá nhiều điều tương tự trong RxJava (các mục ngang của bộ sưu tập), nhưng, vì RxJava tập trung vào nhiệm vụ đồng thời, ..., nó sử dụng đồng bộ hóa, chốt, ... Vì vậy, cùng một tác vụ sử dụng RxJava có thể chậm hơn với luồng Java 8.
RxJava có thể được so sánh với CompletableFuture
, nhưng điều đó có thể tính toán nhiều hơn chỉ một giá trị.
parallelStream
hỗ trợ đồng bộ hóa tương tự các đường ngang / bản đồ / lọc đơn giản, v.v.
Có một số khác biệt về kỹ thuật và mang thai, ví dụ, các luồng Java 8 là các chuỗi giá trị được sử dụng một lần, dựa trên kéo, trong khi RxJava Observables có thể quan sát được, dựa trên kéo thích ứng, các chuỗi có giá trị không đồng bộ. RxJava nhắm đến Java 6+ và cũng hoạt động trên Android.
Luồng Java 8 dựa trên kéo. Bạn lặp lại một luồng Java 8 tiêu thụ từng mục. Và nó có thể là một dòng vô tận.
RXJava Observable
theo mặc định dựa trên đẩy. Bạn đăng ký một Đài quan sát và bạn sẽ nhận được thông báo khi mục tiếp theo đến ( onNext
) hoặc khi luồng hoàn thành ( onCompleted
) hoặc khi xảy ra lỗi ( onError
). Bởi vì với Observable
bạn nhận được onNext
, onCompleted
, onError
sự kiện, bạn có thể làm một số chức năng mạnh mẽ như cách kết hợp khác nhau Observable
s để một hình mới ( zip
, merge
, concat
). Những thứ khác bạn có thể làm là lưu trữ bộ đệm, điều chỉnh, ... Và nó sử dụng ít nhiều cùng một API trong các ngôn ngữ khác nhau (RxJava, RX bằng C #, RxJS, ...)
Theo mặc định RxJava là luồng đơn. Trừ khi bạn bắt đầu sử dụng Trình lập lịch biểu, mọi thứ sẽ diễn ra trên cùng một chuỗi.
Các câu trả lời hiện có là toàn diện và chính xác, nhưng một ví dụ rõ ràng cho người mới bắt đầu là thiếu. Cho phép tôi đặt một số cụ thể đằng sau các thuật ngữ như "đẩy / kéo dựa" và "có thể quan sát lại". Lưu ý : Tôi ghét thuật ngữ này Observable
(đó là một luồng vì lợi ích của thiên đường), vì vậy sẽ chỉ đơn giản đề cập đến các luồng J8 vs RX.
Hãy xem xét một danh sách các số nguyên,
digits = [1,2,3,4,5]
Luồng J8 là một tiện ích để sửa đổi bộ sưu tập. Ví dụ, các chữ số chẵn có thể được trích xuất là,
evens = digits.stream().filter(x -> x%2).collect(Collectors.toList())
Về cơ bản, đây là bản đồ, bộ lọc, thu nhỏ của Python , một bổ sung rất hay (và quá hạn dài) cho Java. Nhưng điều gì sẽ xảy ra nếu các chữ số không được thu thập trước thời hạn - điều gì sẽ xảy ra nếu các chữ số đang phát trực tuyến trong khi ứng dụng đang chạy - chúng ta có thể lọc các số chẵn trong thời gian thực không.
Hãy tưởng tượng một quy trình xử lý luồng riêng biệt xuất ra số nguyên vào các thời điểm ngẫu nhiên trong khi ứng dụng đang chạy ( ---
biểu thị thời gian)
digits = 12345---6------7--8--9-10--------11--12
Trong RX, even
có thể phản ứng với từng chữ số mới và áp dụng bộ lọc trong thời gian thực
even = -2-4-----6---------8----10------------12
Không cần lưu trữ danh sách đầu vào và đầu ra. Nếu bạn muốn có một danh sách đầu ra, không có vấn đề gì có thể phát trực tuyến. Trong thực tế, tất cả mọi thứ là một luồng.
evens_stored = even.collect()
Đây là lý do tại sao các thuật ngữ như "không trạng thái" và "chức năng" được liên kết nhiều hơn với RX
RxJava cũng liên quan chặt chẽ với sáng kiến luồng phản ứng và tự coi đó là một triển khai đơn giản của API luồng phản ứng (ví dụ so với triển khai luồng Akka ). Sự khác biệt chính là, các luồng phản ứng được thiết kế để có thể xử lý áp lực ngược, nhưng nếu bạn xem trang luồng phản ứng, bạn sẽ có ý tưởng. Họ mô tả các mục tiêu của họ khá tốt và các luồng cũng liên quan chặt chẽ đến tuyên ngôn phản ứng .
Các luồng Java 8 khá nhiều khi thực hiện một bộ sưu tập không giới hạn, khá giống với Scala Stream hoặc Clojure lười biếng seq .
Luồng Java 8 cho phép xử lý các bộ sưu tập thực sự lớn một cách hiệu quả, trong khi tận dụng các kiến trúc đa lõi. Ngược lại, RxJava được phân luồng đơn theo mặc định (không có Trình lập lịch biểu). Vì vậy, RxJava sẽ không tận dụng các máy đa lõi trừ khi bạn tự viết mã logic đó.