我需要在Clojure程序中实现无限操作。我希望Java程序员的语法也相当清楚:
(defn- my-operation
(future
(while @continue
(do things)
(Thread/sleep polling-time)))
这给了我我想要的东西,在不同的线程中的操作,所以它不会阻止主要的,并且还有一个非常清晰和直接的语法,而不必处理本机Java函数,这将迫使我使用点特殊形式。
但Java未来的定义是异步计算结果的表示"在这种情况下,我并没有真正对结果做任何事情。
答案 0 :(得分:5)
这将占用Clojure管理的线程池中的一个线程,并用于此类事情。该线程池的预期用途是用于短期运行操作,因此它是一种误用。此外,future
背后的意图是计算一次值,以便可以多次解除引用,以便也可以滥用。
长期运行的任务有很多其他选项,包括使用Java的Executor框架,核心异步或启动自己的线程。
(defonce background-thread (doto (Thread. (fn []
(while @continue
(do things)
(Thread/sleep polling-time))))
(.setDaemon true)
(.start)))
正如其他人所提到的,可能值得考虑未处理的异常。 Stuart Sierra的博文是great place to start。
future
的文档字符串表示它会返回您可以调用deref
的内容。它的引用类型与delay
或atom
的引用方式相同,它具有如何获得价值的语义,而且它可以是真的。只是创造一个未来,让它永远运行,如果你看到某些代码的未来,它意味着你关心它产生的价值。
(clojure.repl/doc future)
-------------------------
clojure.core/future
([& body])
Macro
Takes a body of expressions and yields a future object that will
invoke the body in another thread, and will cache the result and
return it on all subsequent calls to deref/@. If the computation has
not yet finished, calls to deref/@ will block, unless the variant of
deref with timeout is used. See also - realized?.
答案 1 :(得分:2)
还应该注意的是,Future
将吞下发生在其中的所有异常,直到它们被取消引用。如果你从未打算取消引用它们,请准备好流泪。
我已经被多次多次次咬了一下,突然间一切都没有明显的原因停止工作。只是后来我意识到发生了一个我不知道的异常。
与@ l0st建议的一样,这就是我一直在使用的简单案例:
(defmacro thread [& body]
`(doto (Thread. (fn [] ~@body)
(.start))))
然后传递给thread
的所有内容都将隐式运行在一个新线程中,允许您编写:
(thread
(while @continue
(stuff)))
在语法方面,这基本上就是你以前所拥有的。请注意,如果您决定使用use
Clojure.Async,那么当然这会影响具有相同名称的宏。
雅,处理Java互操作是一件痛苦的事,但是如果你只是把它藏起来,它可以带来一些不错的自定义代码。