我有一个用Clojure编写的Web服务。它实现了一个简单的GET方法,它返回一个JSON对象,表示路由器的当前位置和不同的时间计数器。
我的代码有一堆原子来跟踪时间。每个原子代表机器在给定时间可能正在进行的不同活动。例如:校准,空闲,卡住或工作:
(def idle-time (atom 0))
(def working-time (atom 0))
(def stuck-time (atom 0))
(def calibration-time (atom 0))
接近结束时,我有一个循环,每隔15秒更新位置和时间计数器:
(defn update-machine-info []
(let [machine-info (parse-data-files)]
(update-time-counters machine-info)
(reset! new-state (merge machine-info
{:idleCounter @idle-time
:workingCounter @working-time
:stuckCounter @stuck-time
:calibrationCounter @calibration-time}))))
(loop []
(future
(Thread/sleep 15000)
(update-machine-info)
(recur)))
目前此代码遇到竞争条件,这意味着位置和时间计数器未更新。但是,Web服务仍然会响应正确的JSON响应,尽管它具有旧值。
Web Service正在使用Cheshire生成映射到JSON,这里是我的GET实现:
(defroutes app-routes
(GET "/" [] (resource :available-media-types ["application/json"]
:handle-ok (generate-string (get-machine-information))))
(route/not-found "Not Found"))
我应该使用ref而不是原子吗?我正确使用未来吗?是(Thread / sleep 15000)导致问题,因为原子是异步的吗?
如果您在我的代码中看到明显的错误,请告诉我。
答案 0 :(得分:1)
我不认为你可以在未来可靠地重复出现在未来之外的循环(不完全确定),但为什么不尝试这样的东西呢?
<View... android:visibility="gone"/>
or
<View... android:visibility="invisible"/>
这样循环/重复停留在同一个线程中。
除此之外,如果更新机器计数器抛出异常,循环将停止,您将永远不会看到异常,因为永远不会取消引用未来。代理(http://clojure.org/agents)可能更适合这种情况,因为您可以注册错误处理程序。
答案 1 :(得分:0)
我认为正在发生的事情是,您调用期货的过程在您的期货实际执行之前终止。对于你的所作所为,期货可能是错误的构造类型。我也不认为您的循环未来录音序列正在按照您的想法进行。
这里有很多猜测,因为不清楚你究竟在哪里定义和调用你的代码。我想您可能想要使用类似代理的东西,您需要在根进程中设置它们,然后在返回响应之前在处理程序中向它们发送消息。