在Clojure中编写线程安全文件

时间:2013-04-17 16:29:52

标签: clojure

我正在玩线程安全文件写入,我无法弄清楚为什么这段代码没有记录到文件中(基于http://blakesmith.me/2012/05/25/understanding-clojure-concurrency-part-2.html的代理部分)

代码正在执行所有正确的功能,但文件仍为空。我认为这是因为文件关闭并没有以某种方式发生,但即使是对未来的影响也会迫使接近尾声,因为测试似乎没有帮助。

(defn write-out [out msg]
  (.write out msg)
  out)

(defn log [logger msg]
  (send logger write-out msg))

(defn close [logger]
  (send logger #(.close %)))

(defn go []
  (let [ofile (agent (clojure.java.io/writer "/tmp/log.test.txt" :append true))]
    (dotimes [x 10]
      (future (log ofile (str "Log A " x "\n"))))
    (close ofile)
    (shutdown-agents)))

小额奖金问题:帖子链接从未真正解释为什么我需要在写出结束时返回文件编写器指针。我知道你需要它,但我不确定为什么。

2 个答案:

答案 0 :(得分:3)

也许您需要致电(.flush out)

您的函数需要返回out,以便代理具有它接收的下一个defn调用的值。写入文件本身就是副作用。

agent的典型示例用例是多个线程“递增”(好,由新的递增值替换)的计数器。但是,在这种情况下,您不是递增计数器,而是写入outOutputStream实例)。因此必须返回out,以便将其传递给下一个代理任务。

我发现有用的博文: http://lethain.com/a-couple-of-clojure-agent-examples/

答案 1 :(得分:1)

请注意,即使您按照另一个答案中的建议刷新文件,此代码的行为也是不确定的。例如,在第一次调度之前,所有10个生成的futures可能需要一段时间,因此在它们开始之前,-main函数已经在记录器上排队(close ofile)个动作:在这种情况下,所有写入尝试都将失败。事实上,在任何期货开始之前,甚至可能都会调用shutdown-agents:那么他们的send行动都不会产生任何影响!