使用 Java 未来进行无限操作是错误的吗?
Is it wrong to use a Java future for an infinite operation?
我需要在 Clojure 程序中实现无限操作。我希望 Java 程序员的语法也相当清晰:
(defn- my-operation
(future
(while @continue
(do things)
(Thread/sleep polling-time)))
这正是我想要的,在不同的线程中进行操作,因此它不会阻塞主线程,而且语法非常清晰直接,无需处理本机 Java 函数强制我使用点特殊形式。
但是 Java 未来的定义是 "representation of the result of an asynchronous computation",在这种情况下,好吧,我实际上并没有对结果做任何事情。
- 这样使用它们是错误的吗?。
- 与开始我自己的线程相比,是否有任何让我担心的技术差异?
- 这在语义上是错误的吗?
这将在 Clojure 管理的线程池中占用一个线程,并用于此类事情。该线程池的预期用途是用于简短的 运行ning 操作,因此这是一种误用。此外,future
背后的意图是计算一次值,以便可以多次取消引用它,所以这也是一种误用。
长 运行ning 任务还有很多其他选项,包括使用 Java 的执行器框架、核心异步或启动您自己的线程。
(defonce background-thread (doto (Thread. (fn []
(while @continue
(do things)
(Thread/sleep polling-time))))
(.setDaemon true)
(.start)))
正如其他人所提到的,可能值得考虑未处理的异常。 Stuart Sierra 的博客 post 是 great place to start.
future
的文档字符串说它 returns 你可以调用 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?.
还应注意,Future
s 将吞并其中发生的所有异常,直到 它们被解除引用。如果您从不打算取消对它们的引用,请做好泪流满面的准备。
我被这个问题 多次 次,突然间一切都无缘无故地停止工作。后来我才知道发生了一个我不知道的异常。
按照@l0st 的建议,这就是我在简单案例中使用的方法:
(defmacro thread [& body]
`(doto (Thread. (fn [] ~@body)
(.start))))
然后传递给 thread
的所有内容都将在新线程中隐式 运行,这样您就可以编写:
(thread
(while @continue
(stuff)))
这基本上就是您之前在语法方面的内容。请注意,如果您决定 use
Clojure.Async,这当然会影响具有相同名称的宏。
是的,处理 Java 互操作很痛苦,但如果你只是把它藏在某个地方,它可以产生一些不错的自定义代码。
我需要在 Clojure 程序中实现无限操作。我希望 Java 程序员的语法也相当清晰:
(defn- my-operation
(future
(while @continue
(do things)
(Thread/sleep polling-time)))
这正是我想要的,在不同的线程中进行操作,因此它不会阻塞主线程,而且语法非常清晰直接,无需处理本机 Java 函数强制我使用点特殊形式。
但是 Java 未来的定义是 "representation of the result of an asynchronous computation",在这种情况下,好吧,我实际上并没有对结果做任何事情。
- 这样使用它们是错误的吗?。
- 与开始我自己的线程相比,是否有任何让我担心的技术差异?
- 这在语义上是错误的吗?
这将在 Clojure 管理的线程池中占用一个线程,并用于此类事情。该线程池的预期用途是用于简短的 运行ning 操作,因此这是一种误用。此外,future
背后的意图是计算一次值,以便可以多次取消引用它,所以这也是一种误用。
长 运行ning 任务还有很多其他选项,包括使用 Java 的执行器框架、核心异步或启动您自己的线程。
(defonce background-thread (doto (Thread. (fn []
(while @continue
(do things)
(Thread/sleep polling-time))))
(.setDaemon true)
(.start)))
正如其他人所提到的,可能值得考虑未处理的异常。 Stuart Sierra 的博客 post 是 great place to start.
future
的文档字符串说它 returns 你可以调用 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?.
还应注意,Future
s 将吞并其中发生的所有异常,直到 它们被解除引用。如果您从不打算取消对它们的引用,请做好泪流满面的准备。
我被这个问题 多次 次,突然间一切都无缘无故地停止工作。后来我才知道发生了一个我不知道的异常。
按照@l0st 的建议,这就是我在简单案例中使用的方法:
(defmacro thread [& body]
`(doto (Thread. (fn [] ~@body)
(.start))))
然后传递给 thread
的所有内容都将在新线程中隐式 运行,这样您就可以编写:
(thread
(while @continue
(stuff)))
这基本上就是您之前在语法方面的内容。请注意,如果您决定 use
Clojure.Async,这当然会影响具有相同名称的宏。
是的,处理 Java 互操作很痛苦,但如果你只是把它藏在某个地方,它可以产生一些不错的自定义代码。