ทั้งฟิวเจอร์สและสัญญาจะปิดกั้นจนกว่าพวกเขาจะคำนวณมูลค่าของมันแล้วอะไรคือความแตกต่างระหว่างพวกเขา?
ทั้งฟิวเจอร์สและสัญญาจะปิดกั้นจนกว่าพวกเขาจะคำนวณมูลค่าของมันแล้วอะไรคือความแตกต่างระหว่างพวกเขา?
คำตอบ:
การตอบในเงื่อนไข Clojure นี่คือตัวอย่างบางส่วนจากscreencast ของ Sean Devlin :
(def a-promise (promise))
(deliver a-promise :fred)
(def f (future (some-sexp)))
(deref f)
โปรดทราบว่าในสัญญาคุณจะส่งมอบค่าที่คุณเลือกอย่างชัดเจนในการคำนวณ:fred
ในภายหลัง ( ในกรณีนี้) ในทางกลับกันอนาคตกำลังถูกเผาผลาญในสถานที่เดียวกับที่สร้างขึ้น some-expr
มีการเปิดตัวคงจะอยู่เบื้องหลังและการคำนวณในตีคู่ (ในที่สุด) แต่ถ้ามันยังคงอยู่ unevaluated ตามเวลาที่มันมีการเข้าถึงบล็อกด้ายจนกว่าจะสามารถใช้ได้
แก้ไขเพื่อเพิ่ม
เพื่อช่วยแยกความแตกต่างระหว่างคำสัญญากับอนาคตให้สังเกตสิ่งต่อไปนี้:
promise
. ขณะนี้วัตถุสัญญานั้นสามารถส่งผ่านไปยังเธรดใดก็ได้deliver
ผลลัพธ์ไปยังวัตถุสัญญานั้นderef
ตามสัญญาก่อนที่คุณจะคำนวณเสร็จจะถูกบล็อกจนกว่าคุณจะทำเสร็จ เมื่อคุณทำเสร็จและคุณได้deliver
แก้ไขสัญญาแล้วคำสัญญาจะไม่ปิดกั้นอีกต่อไปderef
เป็นอนาคต หากการคำนวณเสร็จสมบูรณ์แล้วคุณจะได้รับผลลัพธ์ของมัน หากยังไม่เสร็จสมบูรณ์คุณจะบล็อกจนกว่าจะมี (สันนิษฐานว่าหากยังไม่เริ่มทำงานแสดงderef
ว่าเริ่มดำเนินการแล้ว แต่ก็ไม่รับประกันเช่นกัน)ในขณะที่คุณสามารถทำให้นิพจน์ในอนาคตมีความซับซ้อนเหมือนกับโค้ดที่เป็นไปตามการสร้างคำสัญญา แต่ก็น่าสงสัยว่าเป็นที่พึงปรารถนา ซึ่งหมายความว่าฟิวเจอร์สเหมาะกับการคำนวณที่รวดเร็วและสามารถทำงานในเบื้องหลังได้มากขึ้นในขณะที่สัญญานั้นเหมาะกับเส้นทางการดำเนินการที่มีขนาดใหญ่และซับซ้อน ดูเหมือนสัญญาในแง่ของการคำนวณที่มีอยู่มีความยืดหยุ่นมากขึ้นเล็กน้อยและมุ่งเน้นไปที่ผู้สร้างสัญญาที่ทำงานและเธรดอื่นที่เกี่ยวกับการเก็บเกี่ยว ฟิวเจอร์สมุ่งเน้นไปที่การเริ่มต้นเธรดโดยอัตโนมัติ (โดยไม่มีค่าใช้จ่ายที่น่าเกลียดและเกิดข้อผิดพลาดได้ง่าย) และดำเนินต่อไปกับสิ่งอื่น ๆ จนกว่าคุณ - เธรดต้นทาง - ต้องการผลลัพธ์
future
โทรสามารถรวม N sexprs ได้
ทั้งอนาคตและสัญญาเป็นกลไกในการสื่อสารผลลัพธ์ของการคำนวณแบบอะซิงโครนัสจาก Producer ไปยังผู้บริโภค
ในกรณีของอนาคตการคำนวณจะถูกกำหนดในช่วงเวลาของการสร้างอนาคตและการดำเนินการแบบ async จะเริ่มต้น "ASAP" นอกจากนี้ยัง "รู้" วิธีสร้างการคำนวณแบบอะซิงโครนัส
ในกรณีที่สัญญาคำนวณมันเวลาเริ่มต้นและ [ไปได้] ตรงกันภาวนาจะหลุดพ้นจากกลไกการส่งมอบ เมื่อผลการคำนวณพร้อมใช้งาน Producer ต้องเรียกdeliver
อย่างชัดเจนซึ่งหมายความว่า Producer จะควบคุมเมื่อผลลัพธ์พร้อมใช้งาน
สำหรับสัญญา Clojure ทำผิดการออกแบบโดยใช้วัตถุเดียวกัน (ผลจากการpromise
โทร) ทั้งการผลิต ( deliver
) และบริโภค ( deref
) ผลจากการคำนวณ นี่เป็นสองความสามารถที่แตกต่างกันมากและควรได้รับการปฏิบัติเช่นนี้
promise
สะดวก ผู้บริโภคที่ 'ชั่ว' หายาก ไม่มีอะไรหยุดคุณจากการสร้างสิ่งที่เป็นนามธรรมของคุณเองนอกเหนือจากคำสัญญา
(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))))
มีคำตอบที่ยอดเยี่ยมอยู่แล้วจึงเพิ่มเฉพาะสรุป "วิธีใช้" เท่านั้น:
ทั้งสอง
การสร้างสัญญาหรืออนาคตจะส่งคืนข้อมูลอ้างอิงทันที การอ้างอิงนี้บล็อกบน @ / deref จนกว่าจะมีการจัดเตรียมผลลัพธ์ของการคำนวณโดยเธรดอื่น
อนาคต
เมื่อสร้างอนาคตคุณต้องจัดหางานซิงโครนัสที่ต้องทำ มันดำเนินการในเธรดจากพูลที่ไม่ถูกผูกไว้โดยเฉพาะ
สัญญา
คุณไม่มีข้อโต้แย้งใด ๆ เมื่อสร้างสัญญา การอ้างอิงที่ควรได้รับการส่งผ่านไปยังคนอื่น ๆ ของผู้ใช้ด้ายที่จะdeliver
ส่งผลให้
ใน Clojure, promise
, future
และdelay
มีสัญญาเหมือนวัตถุ ทั้งหมดนี้แสดงถึงการคำนวณที่ลูกค้าสามารถรอได้โดยใช้deref
(หรือ@
) ไคลเอนต์ใช้ผลลัพธ์ซ้ำเพื่อไม่ให้การคำนวณทำงานหลายครั้ง
พวกเขาแตกต่างกันในวิธีการคำนวณ:
future
จะเริ่มต้นการคำนวณในเธรดผู้ปฏิบัติงานอื่น deref
จะบล็อกจนกว่าผลลัพธ์จะพร้อม
delay
จะดำเนินการคำนวณอย่างเฉื่อยชาเมื่อใช้ครั้งแรกของลูกค้าหรือderef
force
promise
deliver
มีความยืดหยุ่นมากที่สุดเป็นผลของมันจะถูกส่งไปในทางที่กำหนดเองโดยใช้ คุณสามารถใช้มันเมื่อค่าfuture
หรือdelay
ตรงกับกรณีการใช้งานของคุณ
ประการแรก a Promise
คือFuture
. ฉันคิดว่าคุณต้องการทราบความแตกต่างระหว่าง a Promise
และFutureTask
.
A Future
หมายถึงค่าที่ยังไม่เป็นที่รู้จักในปัจจุบัน แต่จะทราบในอนาคต
A FutureTask
แสดงถึงผลลัพธ์ของการคำนวณที่จะเกิดขึ้นในอนาคต (อาจจะเป็นเธรดพูล) เมื่อคุณพยายามเข้าถึงผลลัพธ์หากการคำนวณยังไม่เกิดขึ้นระบบจะบล็อก มิฉะนั้นผลลัพธ์จะถูกส่งกลับทันที ไม่มีฝ่ายอื่นที่เกี่ยวข้องในการคำนวณผลลัพธ์เนื่องจากคุณได้ระบุการคำนวณไว้ล่วงหน้า
A Promise
หมายถึงผลลัพธ์ที่ผู้ให้สัญญาจะส่งมอบให้แก่ผู้รับสัญญาในอนาคต ในกรณีนี้คุณคือผู้ให้สัญญาและผู้ให้สัญญาคือผู้ที่ให้Promise
วัตถุแก่คุณ คล้ายกับFutureTask
ถ้าคุณพยายามที่จะเข้าถึงผลก่อนที่จะPromise
ได้รับการเติมเต็มจะได้รับการปิดกั้นจน promiser Promise
ตอบสนอง เมื่อPromise
สำเร็จแล้วคุณจะได้รับค่าเดียวกันเสมอและทันที ซึ่งแตกต่างจาก a FutureTask
มีอีกฝ่ายที่เกี่ยวข้องที่นี่ซึ่งเป็นผู้สร้างไฟล์Promise
. Promise
ที่บุคคลอื่นเป็นผู้รับผิดชอบสำหรับการทำการคำนวณและการตอบสนอง
ในแง่นั้น a FutureTask
คือPromise
คุณสร้างขึ้นเพื่อตัวเอง