这里需要注意的基本事情是:你不能安全地杀死一个没有自己合作的线程。由于您是希望能够过早杀死的功能的拥有者,因此允许该功能合作并优雅而安全地死亡是有道理的。
(defn function-to-run
[]
(while work-not-done
(if-not (Thread/interrupted)
; ... do your work
(throw (InterruptedException. "Function interrupted...")))))
(def t (Thread. (fn []
(try
(while true
(function-to-run))
(catch InterruptedException e
(println (.getMessage e)))))))
要开始线程
(.start t)
要中断它:
(.interrupt t)
你的做法是不足够你的使用情况,因为while
条件进行检查后,才从返回的控制流function-to-run
,但您希望在执行期间停止function-to-run
。这里的方法不同之处在于更频繁地检查条件,即每次通过function-to-run
中的循环。请注意,不是从function-to-run
中抛出异常,您也可以返回一些指示错误的值,只要您的主线程中的循环检查此值,就不必涉及异常。
如果您的function-to-run
未提供可执行interrupted
检查的循环,则它可能正在执行一些阻塞I/O。您可能无法中断此操作,尽管许多API都允许您指定操作的超时时间。在最坏的情况下,您仍然可以在呼叫周围的功能中执行间歇性检查interrupted
。但底线仍然适用:您不能安全地强制停止执行在该函数中运行的代码;它应该合作控制。
注: 我的原始答案在这里介绍了一个例子,其中使用了java的Thread.stop()
(尽管强烈不鼓励)。根据评论中的反馈,我修改了上面的答案。
我完全修改了我的答案,可能想看看它是否适用于您的用例。 – Josh
对于我来说,运行一个代理而不是未来对你的用例来说会更好。即你可以控制一个原子,如果下一次你的代理迭代应该发出:'(如果@running(send * agent * nil))'(因此你甚至不需要'while循环)。您可以根据需要在运行函数中尽可能频繁地检查原子的状态,并在必要时提前返回。 (例如Rich Rich Hickey着名的ants.clj。) –