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
first 实现了序列,但是向量、range
s 或其他序列都会导致并行执行。
为什么在使用时将来调度到同一个线程repeatedly
?
谢谢!
解决方案
这有效:
(dorun (map deref (doall (map #(future (println % (Thread/currentThread))) (repeatedly 10 #(identity 42))))))
问题是range
产生一个分块序列,同时repeatedly
产生一个非分块序列。Map 是惰性的,所以repeatedly
如果你创建一个未来,然后解除它,然后创建下一个未来,然后解除它。在这种range
情况下,序列被分块,因此您正在创建所有期货,然后deref
对所有期货进行 ing。
这是观察分块和非分块序列行为之间差异的另一种有趣方式。
=> (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 的隐藏特性之一,你通常会在它第一次咬你时了解它:)
推荐阅读
- mysql - LEFT - JOIN 和 WHERE 在查询中未按预期工作
- system-verilog - 原语的 SystemVerilog 断言
- c# - 从 xml 文件中选择一个特定的节点(带冒号)并将其绑定到模型类中
- c - 如何使用 C 中的布尔函数确定用户输入是否为数字
- c++ - 如何在 C++ 中的向量中找到子字符串
- javascript - 如何使用 Javascript 将上传的音频转换为 Blob?
- javascript - 如何使用 Jest 和 Express 编写集成测试?
- python - 无法解析 modin 数据框中的一列 json 字符串(适用于 pandas)
- java - 读/写图像的问题
- r - 为什么形式函数在使用参数定义的函数上返回 NULL?