将Java未来用于无限操作是错误的吗?

时间:2018-02-12 10:58:11

标签: java multithreading clojure future java.util.concurrent

我需要在Clojure程序中实现无限操作。我希望Java程序员的语法也相当清楚:

(defn- my-operation
    (future
        (while @continue
            (do things)
            (Thread/sleep polling-time)))

这给了我我想要的东西,在不同的线程中的操作,所以它不会阻止主要的,并且还有一个非常清晰和直接的语法,而不必处理本机Java函数,这将迫使我使用点特殊形式。

但Java未来的定义是异步计算结果的表示"在这种情况下,我并没有真正对结果做任何事情。

  • 以这种方式使用它们是错误的吗?
  • 与启动我自己的Thread相比,是否有任何技术差异应该让我担心?
  • 这在语义上是错误的吗?。

2 个答案:

答案 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的内容。它的引用类型与delayatom的引用方式相同,它具有如何获得价值的语义,而且它可以是真的。只是创造一个未来,让它永远运行,如果你看到某些代码的未来,它意味着你关心它产生的价值。

(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互操作是一件痛苦的事,但是如果你只是把它藏起来,它可以带来一些不错的自定义代码。