Clojure "ซ้ำ ๆ " ทำให้ "อนาคต" ทำงานตามลำดับ


12

ในขณะที่ตัวอย่างนี้

(dorun 
  (map deref 
    (map #(future 
            (println % (Thread/currentThread))) 
         (range 10))))

พิมพ์ 10 เส้นผสมที่แสดงหัวข้อที่แตกต่าง:

0 #object[java.lang.Thread 0x5f1b4a83 Thread[clojure-agent-send-off-pool-26,5,main]]                                                                                                                           
2 #object[java.lang.Thread 1 0x79dfba1f #object[Thread[clojure-agent-send-off-pool-28,5,main]java.lang.Thread]                                                                                                 
3 4 #object[java.lang.Thread #object[java.lang.Thread 0x7ef7224f Thread[clojure-agent-send-off-pool-27,5,main]0x5f1b4a83 ]Thread[clojure-agent-send-off-pool-26,5,main]]                                       
5                                                                                                                                                                                                              
67  #object[java.lang.Thread #object[0x79dfba1f java.lang.Thread Thread[clojure-agent-send-off-pool-28,5,main]]0x77526645                                                                                      
 8 #object[java.lang.Thread #object[java.lang.ThreadThread[clojure-agent-send-off-pool-29,5,main] ]9 #object[java.lang.Thread 0xc143aa5 0x7ef7224f                                                             Thread[clojure-agent-send-off-pool-31,5,main]]Thread[clojure-agent-send-off-pool-27,5,main]]                                                                                                                       

0x1ce8675f 0x379ae862 Thread[clojure-agent-send-off-pool-30,5,main]Thread[clojure-agent-send-off-pool-32,5,main]]]

อย่างที่ฉันคาดไว้ตัวอย่างต่อไปนี้:

(dorun
  (map deref 
    (map #(future 
            (println % (Thread/currentThread))) 
         (repeatedly 10 #(identity 42)))))

สร้าง 10 สตริงที่จัดเรียงอย่างเรียบร้อยด้วยเธรดเดียวกัน:

42 #object[java.lang.Thread 0x1e1b7ffb Thread[clojure-agent-send-off-pool-39,5,main]]                                                                                                                              
42 #object[java.lang.Thread 0x1e1b7ffb Thread[clojure-agent-send-off-pool-39,5,main]]                                                                                                                              
42 #object[java.lang.Thread 0x1e1b7ffb Thread[clojure-agent-send-off-pool-39,5,main]]                                                                                                                              
42 #object[java.lang.Thread 0x1e1b7ffb Thread[clojure-agent-send-off-pool-39,5,main]]                                                                                                                              
42 #object[java.lang.Thread 0x1e1b7ffb Thread[clojure-agent-send-off-pool-39,5,main]]                                                                                                                              
42 #object[java.lang.Thread 0x1e1b7ffb Thread[clojure-agent-send-off-pool-39,5,main]]                                                                                                                              
42 #object[java.lang.Thread 0x1e1b7ffb Thread[clojure-agent-send-off-pool-39,5,main]]                                                                                                                              
42 #object[java.lang.Thread 0x1e1b7ffb Thread[clojure-agent-send-off-pool-39,5,main]]                                                                                                                              
42 #object[java.lang.Thread 0x1e1b7ffb Thread[clojure-agent-send-off-pool-39,5,main]]                                                                                                                              
42 #object[java.lang.Thread 0x1e1b7ffb Thread[clojure-agent-send-off-pool-39,5,main]]                          

ซึ่งบ่งชี้อย่างชัดเจนว่าฟิวเจอร์สไม่ได้ทำงานในแบบคู่ขนาน แต่แต่ละรายการในเธรดเดียวกัน

สิ่งนี้เกิดขึ้นกับrepeatedlyแม้ว่าฉันจะรู้ลำดับdoallแรก แต่เวกเตอร์ranges หรือลำดับอื่น ๆ ทั้งหมดส่งผลให้มีการดำเนินการแบบขนาน

ทำไมการจัดส่งไปยังเธรดเดียวกันในอนาคตเมื่อrepeatedlyมีการใช้

ขอบคุณ!

คำตอบ:


13

งานนี้:

(dorun (map deref (doall (map #(future (println % (Thread/currentThread))) (repeatedly 10 #(identity 42))))))

ปัญหาคือว่าrangeผลิตchunkedลำดับในขณะที่การrepeatedlyผลิตunchunkedลำดับ แผนที่ขี้เกียจดังนั้นในrepeatedlyกรณีที่คุณกำลังสร้างอนาคตจากนั้นทำการยกเลิกการลงทะเบียนจากนั้นสร้างอนาคตต่อไปจากนั้นทำการยกเลิกการลงทะเบียน ในrangeกรณีที่ลำดับถูกทำให้เป็นก้อนดังนั้นคุณจะสร้างอนาคตทั้งหมดแล้วรวมderefทั้งหมด

ต่อไปนี้เป็นวิธีที่สนุกอีกวิธีหนึ่งในการสังเกตความแตกต่างระหว่างลักษณะการทำงานของลำดับที่มีการสับเปลี่ยนกัน

=> (first (map prn (range 10)))
0
1
2
3
4
5
6
7
8
9
nil
=> (first (map prn (repeatedly 10 #(identity 13))))
13
nil

ขนาดของชิ้นมักจะเป็น 32 ( แต่ผมคิดว่าไม่รับประกันใดก็ได้) (first (map prn (range 1000)))ที่สามารถเห็นได้ถ้าคุณทำงาน

Chunking เป็นหนึ่งในคุณสมบัติที่ซ่อนอยู่ของ Clojure ที่คุณมักจะเรียนรู้เมื่อมันกัดคุณครั้งแรก :)


1
โว้ว! [แทรกการสมรู้ร่วมคิด Keanu Reaves memehere]: ฉันไม่เห็นการมานี้! ขอบคุณสำหรับคำตอบที่ยอดเยี่ยม!
Rick77

1
ไม่มีปัญหา! ฉันเห็นคำถามนี้เพียงเพราะคุณโพสต์ไว้ที่ #clojure บน freenode
opqdonut
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.