Cả hợp đồng tương lai và lời hứa đều chặn cho đến khi chúng tính được giá trị của chúng, vậy sự khác biệt giữa chúng là gì?
Cả hợp đồng tương lai và lời hứa đều chặn cho đến khi chúng tính được giá trị của chúng, vậy sự khác biệt giữa chúng là gì?
Câu trả lời:
Trả lời bằng thuật ngữ Clojure, đây là một số ví dụ từ video truyền hình của Sean Devlin :
(def a-promise (promise))
(deliver a-promise :fred)
(def f (future (some-sexp)))
(deref f)
Lưu ý rằng trong lời hứa, bạn đang cung cấp một cách rõ ràng một giá trị mà bạn chọn trong một lần tính toán sau ( :fred
trong trường hợp này). Mặt khác, tương lai đang được tiêu thụ ở chính nơi mà nó được tạo ra. Có some-expr
lẽ nó được khởi chạy ở hậu trường và được tính toán song song (cuối cùng), nhưng nếu nó vẫn không được đánh giá vào thời điểm nó được truy cập vào các khối chuỗi cho đến khi nó có sẵn.
đã chỉnh sửa để thêm
Để giúp phân biệt rõ hơn giữa lời hứa và tương lai, hãy lưu ý những điều sau:
promise
. Đối tượng hứa đó bây giờ có thể được chuyển đến bất kỳ luồng nào.deliver
kết quả cho đối tượng hứa đó.deref
lời hứa của bạn trước khi bạn hoàn thành tính toán của mình sẽ bị chặn cho đến khi bạn hoàn thành. Khi bạn đã hoàn thành và bạn đã thực hiện deliver
lời hứa, thì lời hứa sẽ không còn cản trở nữa.deref
là tương lai. Nếu phép tính đã hoàn thành, bạn sẽ nhận được kết quả của nó. Nếu nó chưa hoàn thành, bạn chặn cho đến khi nó có. (Có lẽ nếu nó chưa bắt đầu, deref
thì nó có nghĩa là nó bắt đầu thực thi, nhưng điều này cũng không được đảm bảo.)Mặc dù bạn có thể làm cho biểu thức trong tương lai phức tạp như mã sau khi tạo ra một lời hứa, nhưng có lẽ điều đó là mong muốn. Điều này có nghĩa là các hợp đồng tương lai thực sự phù hợp hơn với các tính toán nhanh, có thể chạy nền trong khi các hứa hẹn thực sự phù hợp hơn với các đường dẫn thực thi lớn và phức tạp. Ngoài ra, các lời hứa dường như, về mặt tính toán có sẵn, linh hoạt hơn một chút và hướng đến người tạo lời hứa đang thực hiện công việc và một chuỗi khác gặt hái mùa màng. Các hợp đồng tương lai có xu hướng tự động bắt đầu một chuỗi (không có chi phí xấu và dễ xảy ra lỗi) và tiếp tục với những thứ khác cho đến khi bạn - chuỗi ban đầu - cần kết quả.
future
cuộc gọi có thể bao gồm N sexprs.
Cả Tương lai và Hứa hẹn đều là cơ chế truyền đạt kết quả tính toán không đồng bộ từ Nhà sản xuất đến (các) Người tiêu dùng.
Trong trường hợp Tương lai , tính toán được xác định tại thời điểm tạo Tương lai và quá trình thực thi không đồng bộ bắt đầu "ASAP". Nó cũng "biết" cách sinh ra một phép tính không đồng bộ.
Trong trường hợp của Promise các tính toán , nó thời gian bắt đầu và [có thể] không đồng bộ gọi được tách riêng từ cơ chế giao hàng. Khi có kết quả tính toán, Producer phải gọi deliver
một cách rõ ràng, điều này cũng có nghĩa là Producer kiểm soát khi nào có kết quả.
Đối với Promises, Clojure mắc lỗi thiết kế khi sử dụng cùng một đối tượng (kết quả của promise
lệnh gọi) để tạo ra ( deliver
) và tiêu thụ ( deref
) kết quả của tính toán . Đây là hai khả năng rất khác biệt và nên được xử lý như vậy.
promise
có thuận tiện hay không. Người tiêu dùng 'ác' rất hiếm; không có gì ngăn cản bạn xây dựng sự trừu tượng của riêng bạn trên những lời hứa.
(defn undeliverable-promise [] (let [p (promise)] (reify clojure.lang.IDeref (deref [_] (deref p)) clojure.lang.IBlockingDeref (deref [_ ms val] (deref p ms val)) clojure.lang.IPending (isRealized [_] (.isRealized p)) clojure.lang.IFn (invoke [_ _] nil))))
Đã có những câu trả lời xuất sắc nên chỉ thêm phần tóm tắt "cách sử dụng":
Cả hai
Tạo lời hứa hoặc tương lai trả về một tham chiếu ngay lập tức. Tham chiếu này chặn trên @ / deref cho đến khi kết quả tính toán được cung cấp bởi luồng khác.
Tương lai
Khi tạo tương lai, bạn cung cấp một công việc đồng bộ sẽ được thực hiện. Nó được thực thi trong một chuỗi từ nhóm không giới hạn chuyên dụng.
Lời hứa
Bạn không đưa ra lý lẽ khi tạo lời hứa. Tham chiếu phải được chuyển đến chuỗi 'người dùng' khác sẽ deliver
dẫn đến kết quả.
Trong Clojure, promise
, future
, và delay
là lời hứa giống như các đối tượng. Tất cả chúng đều đại diện cho một tính toán mà khách hàng có thể chờ đợi bằng cách sử dụng deref
(hoặc @
). Khách hàng sử dụng lại kết quả, do đó tính toán không được chạy nhiều lần.
Chúng khác nhau về cách tính toán được thực hiện:
future
sẽ bắt đầu tính toán trong một luồng công nhân khác. deref
sẽ chặn cho đến khi kết quả sẵn sàng.
delay
sẽ thực hiện tính toán một cách lười biếng, khi khách hàng đầu tiên sử dụng deref
hoặc force
.
promise
cung cấp tính linh hoạt nhất, vì kết quả của nó được phân phối theo bất kỳ cách tùy chỉnh nào bằng cách sử dụng deliver
. Bạn sử dụng nó khi không future
hoặc delay
phù hợp với trường hợp sử dụng của bạn.
Thứ nhất, a Promise
là a Future
. Tôi nghĩ bạn muốn biết sự khác biệt giữa a Promise
và a FutureTask
.
A Future
đại diện cho một giá trị hiện chưa được biết nhưng sẽ được biết trong tương lai.
A FutureTask
đại diện cho kết quả của một phép tính sẽ xảy ra trong tương lai (có thể trong một nhóm luồng nào đó). Khi bạn cố gắng truy cập kết quả, nếu quá trình tính toán vẫn chưa xảy ra, nó sẽ chặn. Nếu không, kết quả được trả về ngay lập tức. Không có bên nào khác tham gia vào việc tính toán kết quả vì việc tính toán được bạn chỉ định trước.
A Promise
đại diện cho một kết quả sẽ được người quảng bá giao cho người được hứa hẹn trong tương lai. Trong trường hợp này, bạn là người hứa và người quảng bá là người đã cho bạn Promise
đồ vật. Tương tự như FutureTask
, nếu bạn cố gắng truy cập kết quả trước khi kết quả Promise
được hoàn thành, nó sẽ bị chặn cho đến khi trình quảng bá hoàn thành Promise
. Sau khi Promise
hoàn thành, bạn sẽ nhận được cùng một giá trị ngay lập tức. Không giống như a FutureTask
, có một bên khác tham gia ở đây, một bên đã tạo ra Promise
. Bên khác có trách nhiệm thực hiện tính toán và thực hiện Promise
.
Theo nghĩa đó, a FutureTask
là một Promise
bạn đã làm cho chính mình.