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, Future
sẽ 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 Streams và Vertx . 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.