【发布时间】:2012-10-04 14:17:32
【问题描述】:
我编写了一个相当原始的测试程序(我正在为 LWJGL 的 OpenGL 类编写一个包装器,主要是出于美观的原因,我决定在其中引入多线程,因为我之前实际上从未编写过并发程序)。 程序结束时,我总是收到警告
我实际上在程序进入主函数之前得到了警告。很抱歉造成混淆(我认为这可能根本不是我的程序,而是 clojure 本身的东西):
Reflection warning, NO_SOURCE_PATH:1 - call to invokeStaticMethod can't be resolved.
我在编译过程中没有收到任何警告,我觉得这很奇怪。无论如何,这是程序:
(ns opengltuts.core
(:import (org.lwjgl.opengl GL11 Display))
(:use opengltuts.opengl)) ;my wrapper
(def world-state (ref {:running true :color [1.0 0.0 0.0 1.0]}))
(defn render-world [state]
(apply glClearColor (:color state))
(glClear GL11/GL_COLOR_BUFFER_BIT)
(Display/update))
(defn render []
(Display/create)
(loop []
(let [world @world-state]
(when (:running world)
(do (render-world world)
(recur)))))
(Display/destroy))
(defn -main []
; without the annotation, I get a warning here too.
(let [render-thread (doto (Thread. ^Runnable render) (.start))]
(Thread/sleep 3000)
(dosync (commute world-state assoc :color [0.0 1.0 0.0 1.0]))
(Thread/sleep 3000)
(dosync (commute world-state assoc :running false))
(.join render-thread)))
这可能不太惯用(我听说在 Clojure 中,您通常不会使用 new Thread 来启动线程,而是使用 Agents 或其他东西,但我还没有完全掌握它是如何工作的),但我猜猜这么短的程序没关系。
【问题讨论】:
-
如果需要简单的线程,可以使用
future代替agent。即(future (render))。另外,Thread/sleep也可以,见clojuredocs.org/clojure_core/clojure.core/future -
你确定警告不是来自
opengltuts.opengl吗?在某处,您正在调用重载的静态方法,但它无法解析确切的调用。关于它发生在运行时,你是在运行时生成代码吗? -
@noahz 不,我没有生成代码。这只发生在程序结束时,当我已经很长时间调用 opengl 函数时。此外,为此使用未来有点奇怪。它确实为我节省了一些点,但现在我需要在最后对 (shutdown-agents) 进行这个奇怪的调用,因为 clojure 无法确定什么时候该退出了。哦,当然,取消引用 nil 值以引起副作用也不适合我。我弄错时间了 - 我在进入主函数之前收到了警告。
-
关于
shutdown-agents- 那是 Java Executor API,而不是 Clojure。您是否使用提前编译? -
提前编译?我在
lein run之前运行lein compile,如果这就是你的意思(确切地说,因为我尽量避免不必要的反思,只要它可以轻松完成)。
标签: clojure