2015-12-11 16 views
21

Tôi muốn viết một phương thức không đồng bộ trả về số CompletableFuture. Mục đích duy nhất của tương lai là theo dõi khi phương pháp hoàn thành, không phải kết quả của nó. Sẽ tốt hơn nếu trả lại CompletableFuture<Void> hoặc CompletableFuture<?>? Có lý do nào để thích cái này hay cái kia, hay chúng có thể hoán đổi cho nhau?Trả lại hoàn tấtFuture <Void> hoặc CompletableFuture <?>?

  • CompletableFuture chính nó trả về CompletableFuture<Void> từ nhiều phương pháp của nó.
  • java.nioFuture<Void> trong AsynchronousSocketChannel: Future<Void> connect(SocketAddress remote).
  • Mặt khác, java.util.concurrent các lớp như và ScheduledExecutorService trả về Future<?>: ví dụ: Future<?> submit(Runnable task).

Lưu ý rằng tôi chỉ hỏi về các loại trả về, không phải danh sách tham số, khai báo biến hoặc ngữ cảnh khác.

+1

Tôi tìm thấy Tương lai rõ ràng hơn: nó giải thích rằng tương lai là tương lai của không có gì. Tương lai nói rằng đó là một tương lai của một cái gì đó không rõ. –

+3

Xem nhận xét về Java 6 đến Java 7 thay đổi, [ở đây] (http://stackoverflow.com/a/12962219/438154). –

Trả lời

6

Tốt nhất là sử dụng CompletableFuture<Void>.

According to this answer được tìm thấy bởi Sotirios Delimanolis, Future<?> là lỗ hổng API nhỏ. Trong Java 6, phương pháp submit() sử dụng một nội bộ Future<Object> và do đó kiểu trả về của nó được đặt thành Future<?>. Trong Java 7, việc triển khai đã thay đổi để sử dụng Future<Void> nội bộ, nhưng đã quá muộn để thay đổi API để giá trị trả về vẫn giữ nguyên là Future<?>.

API Java mới hơn sử dụng Future<Void>CompletableFuture<Void>. Đó là những ví dụ chúng ta nên làm theo.

12

Nó sẽ được tốt hơn để trở CompletableFuture <Void> hoặc CompletableFuture <? >

Có lý do để thích cái này hay cách khác, hoặc chúng có phải là hoán đổi cho nhau không?

Có ba tình huống mà mã có thể ảnh hưởng đến:

  • Runtime - Generics không có ý nghĩa trên đó.
  • Biên dịch - Tôi không thể tưởng tượng trường hợp một số phương pháp sẽ chấp nhận Future<Void> nhưng sẽ không chấp nhận Future<?>.
  • Phát triển - nếu kết quả của Future không có ý nghĩa, thì đó là cách hay để nói về điều đó với người dùng thông qua tuyên bố.

Vì vậy, Future<Void> thích hợp hơn.

7

Nhìn vào CompletableFuture API bạn sẽ thấy rằng CompletableFuture<Void> được sử dụng với tác dụng phụ loại phương pháp hiển thị kết quả không thể có được (vì nó không tồn tại), ví dụ:

CompletableFuture.runAsync(Runnable runnable); 

trả lại một CompletableFuture<Object> ở đây sẽ gây nhầm lẫn vì không có kết quả thực sự, chúng tôi chỉ quan tâm đến việc hoàn thành. Các phương thức mất ConsumersRunnables trả lại CompletableFuture<Void>, ví dụ: thenAccept, thenAcceptAsync. ConsumerRunnable được sử dụng cho các tác dụng phụ nói chung.

Trường hợp sử dụng khác cho Void là khi bạn thực sự không biết kết quả. Ví dụ: CompletableFuture.allOf, danh sách được chuyển có thể là một CompletableFuture có nguồn gốc từ một Runnable, vì vậy chúng tôi không thể có được kết quả.

Đã nói tất cả điều đó, CompletableFuture<Void> chỉ tốt nếu bạn không có tùy chọn khác, nếu bạn có thể trả lại kết quả, vui lòng truy cập kết quả, người gọi có thể chọn hủy nếu họ không quan tâm. Bạn nói rằng bạn chỉ quan tâm đến việc hoàn thành, sau đó có, CompletableFuture<Void> sẽ thực hiện công việc, nhưng người dùng API của bạn sẽ ghét bạn nếu họ biết rằng CompletableFuture<T> là một lựa chọn và bạn đã quyết định thay mặt họ rằng họ sẽ không bao giờ cần kết quả.

3

Loại phù hợp tùy thuộc vào ngữ nghĩa của nó. Tất cả các tùy chọn được liệt kê hứa hẹn hoàn thành tín hiệu và có thể trả về ngoại lệ không đồng bộ.

  • CompletableFuture<Void>: Void thông báo cho người dùng không có kết quả mong đợi.
  • CompletableFuture<?>? nghĩa là loại giá trị chứa không được xác định theo nghĩa là bất kỳ giá trị nào có thể được phân phối.

Lớp CompletableFuture thừa kế một số phương pháp tiện lợi từ CompletionStage. Nhưng nó cũng cho phép người gọi phương pháp của bạn kích hoạt hoàn thành tương lai mà có vẻ sai bởi vì phương pháp của bạn có trách nhiệm báo hiệu sự hoàn thành của chính nó. Ngoài ra còn có một phương pháp cancel(...) là khá vô nghĩa trong việc thực hiện mặc định của CompletableFuture vì nó không hủy bỏ việc thực hiện.

  • Future<Void>: Các Void nói với người sử dụng không có kết quả được mong đợi.
  • Future<?>? nghĩa là loại giá trị chứa không được xác định theo nghĩa là bất kỳ giá trị nào có thể được phân phối.

Future thiếu các phương pháp tiện lợi từ CompletionStage. Nó không cho phép kích hoạt hoàn thành tương lai nhưng việc thực hiện có thể bị hủy bỏ.

tùy chọn tiếp theo là CompletionStage<Void>:

  • CompletionStage<Void>: Các Void nói với người sử dụng không có kết quả được mong đợi. Các phương thức tiện lợi để ràng buộc các trình xử lý có mặt nhưng phương thức cancel(...) thì không. Người gọi phương thức của bạn không thể kích hoạt hoàn thành CompletionStage.
  • <CancellableFuture extends Future<Void> & CompletionStage<Void>>: Đặt các phương thức từ Future<Void>CompletionStage<Void>. Nó nói rằng không có kết quả, phương pháp tiện lợi có mặt cũng như tùy chọn hủy.Người gọi phương thức của bạn không thể kích hoạt hoàn thành CompletionStage.

Sự vắng mặt của phương thức cancel(...) có thể phù hợp với kịch bản của bạn hay không. Do đó, tôi khuyên bạn nên đi với CompletionStage<Void> nếu bạn không cần hủy và sử dụng <CancellableFuture extends Future<Void> & CompletionStage<Void>> nếu bạn yêu cầu tùy chọn hủy việc thực hiện. Nếu bạn chọn <CancellableFuture extends Future<Void> & CompletionStage<Void>>, bạn có thể muốn tự tạo giao diện được kế thừa từ Future<Void>CompletionStage<Void> để sử dụng làm loại trả lại thay vì đặt giao lộ loại dài trực tiếp trong khai báo phương pháp của bạn.

Bạn nên tránh quay trở lại với loại trả lại được khai báo CompletableFuture vì khả năng người gọi kích hoạt hoàn thành tương lai. Làm như vậy cố tình dẫn đến mã khó hiểu và treo đáng ngạc nhiên vì không rõ ràng mã nào chịu trách nhiệm kích hoạt hoàn thành nữa. Sử dụng một trong các loại bị hạn chế hơn được đề cập để cho phép hệ thống kiểu ngăn chặn hoàn thành không chủ ý gây ra bởi người gọi phương thức của bạn.

Các vấn đề liên quan