2017-03-09 38 views
2

我使用立即杀死一个正在运行的线程未来

(def f 
    (future 
     (while (not (Thread/interrupted)) 
     (function-to-run)))) 

(Thread/sleep 100) 
(future-cancel f) 

的时间(100毫秒)指定金额后取消我的代码。
问题是,我需要取消已运行的函数'function-to-run',重要的是它在100ms后真正停止执行该函数。
我可以以某种方式将中断的信号传播给函数吗?
该函数不是第三方,我自己写的。

+0

我完全修改了我的答案,可能想看看它是否适用于您的用例。 – Josh

+0

对于我来说,运行一个代理而不是未来对你的用例来说会更好。即你可以控制一个原子,如果下一次你的代理迭代应该发出:'(如果@running(send * agent * nil))'(因此你甚至不需要'while循环)。您可以根据需要在运行函数中尽可能频繁地检查原子的状态,并在必要时提前返回。 (例如Rich Rich Hickey着名的ants.clj。) –

回答

5

这里需要注意的基本事情是:你不能安全地杀死一个没有自己合作的线程。由于您是希望能够过早杀死的功能的拥有者,因此允许该功能合作并优雅而安全地死亡是有道理的。

(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()(尽管强烈不鼓励)。根据评论中的反馈,我修改了上面的答案。

+0

谢谢,这就是我想要的。它早已结束,但似乎还没有立即结束。立即杀人不可能?无论如何,这比以前好多了。 – buggy3

+2

'Thread/stop'在[javadoc]中注有巨大的生物危害/放射性/死亡标志(https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#stop( ))。安全使用不仅非常困难,而且安全使用也是不可能的,您绝对不应该使用它。弃用通知附带说明您应该做什么,而且确实是解决此问题的完美解决方案。 – amalloy

+0

你不应该使用Thread.stop()。可以改为使用Thread.interrupt()。您可以捕获并处理函数中的InterruptedException。如果实际上阻止了I/O操作,这可能会也可能不会工作(请阅读操作文档),您应该考虑其他选项。 –

相关问题