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生産チャンクながらシーケンスをrepeatedly生成unchunkedシーケンスを。マップは遅延しているのでrepeatedly、未来を作成している場合は、それを参照解除し、次の未来を作成し、それから派生させます。ではrange、あなたがすべての先物を作成しているので、ケースシーケンスはチャンクされderef、それらのすべてをINGの。

チャンクされたシーケンスとチャンクされていないシーケンスの動作の違いを観察するもう1つの楽しい方法を次に示します。

=> (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)))

チャンクは、Clojureの隠された機能の1つであり、最初に噛まれたときに通常学習します。


1
うわあ![陰謀キアヌ・リーブスmemehereを挿入してください]:私はこれが来るのを見ませんでした!すばらしい答えをありがとう!
Rick77

1
問題ない!この質問は、freenodeの#clojureに投稿したため、見ただけです。
opqdonut
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.