[clojure] Clojure는 “반복적으로” “미래”를 순차적으로 실행합니다

이 발췌문 동안

(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가 사용될 때 왜 동일한 스레드로 디스패치 합니까?

감사!



답변

이것은 작동합니다 :

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

문제는 즉 range생성 청크 동안 시퀀스 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))).

청킹은 Clojure의 숨겨진 기능 중 하나입니다.


답변