Sự khác biệt giữa Có thể quan sát được, Tương lai và RxJava có thể quan sát được


193

Tôi muốn biết sự khác biệt giữa CompletableFuture, FutureObservable RxJava.

Những gì tôi biết là tất cả đều không đồng bộ nhưng

Future.get() chặn luồng

CompletableFuture đưa ra các phương thức gọi lại

RxJava Observable--- tương tự như CompletableFuturevới các lợi ích khác (không chắc chắn)

Ví dụ: nếu khách hàng cần thực hiện nhiều cuộc gọi dịch vụ và khi chúng tôi sử dụng Futures(Java) Future.get()sẽ được thực hiện tuần tự ... muốn biết làm thế nào tốt hơn trong RxJava ..

Và tài liệu http://reactivex.io/intro.html nói

Thật khó để sử dụng Futures để tối ưu hóa các luồng thực thi không đồng bộ có điều kiện (hoặc không thể, vì độ trễ của mỗi yêu cầu khác nhau khi chạy). Tất nhiên, điều này có thể được thực hiện, nhưng nó nhanh chóng trở nên phức tạp (và do đó dễ bị lỗi) hoặc nó bị chặn sớm trên Future.get (), loại bỏ lợi ích của việc thực thi không đồng bộ.

Thực sự quan tâm để biết làm thế nào RxJavagiải quyết vấn đề này. Tôi thấy khó hiểu từ tài liệu này.


Bạn đã đọc tài liệu cho từng? Tôi hoàn toàn không quen thuộc với RxJava, nhưng tài liệu xuất hiện cực kỳ kỹ lưỡng trong nháy mắt. Nó dường như không thể so sánh với hai tương lai.
FThndry

tôi đã trải qua nhưng không thể hiểu nó khác với tương lai Java như thế nào ... hãy sửa tôi nếu tôi sai
shiv455

Làm thế nào là quan sát tương tự như tương lai?
FThndry

2
muốn biết nó khác nhau như thế nào là khác nhau trong quản lý luồng ?? EX: Future.get () chặn luồng .... nó sẽ được xử lý như thế nào trong Observable ???
shiv455

2
ít nhất nó hơi khó hiểu đối với tôi ... một sự khác biệt cấp cao sẽ thực sự hữu ích !!
shiv455

Câu trả lời:


278

Tương lai

Tương lai được giới thiệu trong Java 5 (2004). Về cơ bản, chúng là các trình giữ chỗ cho kết quả của một hoạt động chưa hoàn thành. Khi hoạt động kết thúc, Futuresẽ chứa kết quả đó. Ví dụ: một hoạt động có thể là một thể hiện Runnable hoặc Callable được gửi đến ExecutorService . Người gửi của hoạt động có thể sử dụng Futuređối tượng để kiểm tra xem hoạt động isDone () hay đợi nó kết thúc bằng cách sử dụng phương thức chặn get () .

Thí dụ:

/**
* A task that sleeps for a second, then returns 1
**/
public static class MyCallable implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
        Thread.sleep(1000);
        return 1;
    }

}

public static void main(String[] args) throws Exception{
    ExecutorService exec = Executors.newSingleThreadExecutor();
    Future<Integer> f = exec.submit(new MyCallable());

    System.out.println(f.isDone()); //False

    System.out.println(f.get()); //Waits until the task is done, then prints 1
}

Hoàn thành tính năng

CompleteableFutures đã được giới thiệu trong Java 8 (2014). Họ là thực chất là một quá trình tiến hóa của tương lai thường xuyên, lấy cảm hứng từ của Google Listenable Futures , một phần của Ổi thư viện. Chúng là Tương lai cũng cho phép bạn xâu chuỗi các nhiệm vụ lại với nhau trong một chuỗi. Bạn có thể sử dụng chúng để nói với một số luồng công nhân để "thực hiện một số nhiệm vụ X và khi bạn hoàn thành, hãy thực hiện việc này bằng cách sử dụng kết quả của X". Sử dụng CompleteableFutures, bạn có thể làm một cái gì đó với kết quả của hoạt động mà không thực sự chặn một luồng để chờ kết quả. Đây là một ví dụ đơn giản:

/**
* A supplier that sleeps for a second, and then returns one
**/
public static class MySupplier implements Supplier<Integer> {

    @Override
    public Integer get() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            //Do nothing
        }
        return 1;
    }
}

/**
* A (pure) function that adds one to a given Integer
**/
public static class PlusOne implements Function<Integer, Integer> {

    @Override
    public Integer apply(Integer x) {
        return x + 1;
    }
}

public static void main(String[] args) throws Exception {
    ExecutorService exec = Executors.newSingleThreadExecutor();
    CompletableFuture<Integer> f = CompletableFuture.supplyAsync(new MySupplier(), exec);
    System.out.println(f.isDone()); // False
    CompletableFuture<Integer> f2 = f.thenApply(new PlusOne());
    System.out.println(f2.get()); // Waits until the "calculation" is done, then prints 2
}

RxJava

RxJava là toàn bộ thư viện để lập trình phản ứng được tạo tại Netflix. Nhìn thoáng qua, nó sẽ có vẻ giống với các luồng của Java 8 . Đó là, ngoại trừ nó mạnh hơn nhiều.

Tương tự như Futures, RxJava có thể được sử dụng để kết hợp một loạt các hành động đồng bộ hoặc không đồng bộ để tạo ra một đường ống xử lý. Không giống như Futures, sử dụng một lần, RxJava hoạt động trên các luồng từ 0 trở lên. Bao gồm các luồng không bao giờ kết thúc với số lượng mục vô hạn. Nó cũng linh hoạt và mạnh mẽ hơn nhiều nhờ một bộ toán tử phong phú không thể tin được .

Không giống như các luồng của Java 8, RxJava cũng có một cơ chế áp lực , cho phép nó xử lý các trường hợp trong đó các phần khác nhau của đường ống xử lý của bạn hoạt động theo các luồng khác nhau, ở các tốc độ khác nhau .

Nhược điểm của RxJava là mặc dù có tài liệu vững chắc, đây là một thư viện đầy thách thức để tìm hiểu do sự thay đổi mô hình liên quan. Mã Rx cũng có thể là một cơn ác mộng để gỡ lỗi, đặc biệt là nếu có nhiều luồng liên quan và thậm chí tệ hơn - nếu cần áp lực.

Nếu bạn muốn tìm hiểu về nó, có cả một trang hướng dẫn khác nhau trên trang web chính thức, cộng với tài liệu chính thức và Javadoc . Bạn cũng có thể xem một số video như video này giới thiệu ngắn gọn về Rx và cũng nói về sự khác biệt giữa Rx và Futures.

Phần thưởng: Luồng phản ứng Java 9

Luồng phản ứng của Java 9 hay còn gọi là API Flow là một tập hợp các Giao diện được triển khai bởi các thư viện luồng phản ứng khác nhau như RxJava 2 , Akka StreamsVertx . Chúng cho phép các thư viện phản ứng này kết nối với nhau, trong khi vẫn duy trì tất cả áp suất ngược quan trọng.


Sẽ thật tuyệt khi đưa ra mã ví dụ về cách Rx thực hiện điều này
Zinan Xing

Vậy bằng cách sử dụng Luồng phản ứng, chúng ta có thể trộn RxJava, Akka và Vertx trong một ứng dụng không?
IgorGanapolsky

1
@IgorGanapolsky Có.
Malt

Trong CompleteableFutures, chúng tôi sử dụng các phương thức gọi lại, các phương thức gọi lại này cũng sẽ chặn nếu đầu ra của một phương thức là đầu vào của các cuộc gọi lại khác. Là khối tương lai với lệnh gọi Future.get (). Tại sao người ta nói rằng Future.get () đang chặn cuộc gọi trong khi CompleteableFutures không chặn. Vui lòng giải thích
Deepak

1
@Federico Chắc chắn rồi. Mỗi Futurelà một giữ chỗ cho một đơn kết quả có thể hoặc chưa hoàn thành. Nếu bạn thực hiện lại thao tác đó, bạn sẽ có một phiên bản mới Future. RxJava xử lý các luồng kết quả có thể đến bất cứ lúc nào. Do đó, một loạt các hoạt động có thể trả về một RxJava có thể quan sát được mà sẽ đưa ra một loạt các kết quả. Nó giống như sự khác biệt giữa một phong bì bưu chính và một ống khí nén giúp bơm thư.
Malt

20

Tôi đã làm việc với Rx Java từ 0.9, bây giờ là 1.3.2 và sắp chuyển sang 2.x Tôi sử dụng điều này trong một dự án tư nhân nơi tôi đã làm việc được 8 năm.

Tôi sẽ không lập trình mà không có thư viện này nữa. Lúc đầu tôi đã hoài nghi nhưng đó là một trạng thái hoàn toàn khác mà bạn cần tạo ra. Im lặng khó khăn ngay từ đầu. Đôi khi tôi đã nhìn vào những viên bi trong nhiều giờ .. lol

Đó chỉ là vấn đề thực hành và thực sự làm quen với dòng chảy (còn gọi là hợp đồng của người quan sát và người quan sát), một khi bạn đến đó, bạn sẽ ghét phải làm điều đó khác.

Đối với tôi không thực sự có nhược điểm trên thư viện đó.

Ca sử dụng: Tôi có chế độ xem màn hình chứa 9 đồng hồ đo (cpu, mem, mạng, v.v ...). Khi bắt đầu chế độ xem, chế độ xem đăng ký chính nó vào một lớp giám sát hệ thống trả về một (khoảng thời gian) có thể quan sát có chứa tất cả dữ liệu trong 9 mét. Nó sẽ đẩy mỗi giây một kết quả mới vào chế độ xem (vì vậy không bỏ phiếu !!!). Điều đó có thể quan sát được sử dụng một sơ đồ phẳng để đồng thời (không đồng bộ!) Lấy dữ liệu từ 9 nguồn khác nhau và đưa kết quả vào một mô hình mới mà chế độ xem của bạn sẽ có trên onNext ().

Làm thế quái nào bạn sẽ làm điều đó với tương lai, hoàn thành, vv ... Chúc may mắn! :)

Rx Java giải quyết nhiều vấn đề trong lập trình cho tôi và làm cho nó dễ dàng hơn nhiều ...

Ưu điểm:

  • Tượng !!! (điều quan trọng cần đề cập, quan trọng nhất có thể)
  • Quản lý luồng ra khỏi hộp
  • Xây dựng trình tự có vòng đời của riêng họ
  • Mọi thứ đều có thể quan sát được nên xích rất dễ dàng
  • Ít mã hơn để viết
  • Bình duy nhất trên classpath (rất nhẹ)
  • Đồng thời cao
  • Không gọi lại địa ngục nữa
  • Dựa trên thuê bao (hợp đồng chặt chẽ giữa người tiêu dùng và nhà sản xuất)
  • Chiến lược backpressure (ngắt mạch như thế)
  • Xử lý và phục hồi lỗi tuyệt vời
  • Tài liệu rất hay (viên bi <3)
  • Hoàn toàn kiểm soát
  • Nhiều hơn nữa ...

Nhược điểm: - Khó kiểm tra


13
~ " Tôi sẽ không lập trình mà không có thư viện này nữa. " Vậy RxJava có phải là tất cả cho tất cả các dự án phần mềm không?
IgorGanapolsky

Nó có hữu ích ngay cả khi tôi không có các sự kiện không đồng bộ?
Mukesh Verma
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.