在Java / Clojure中杀死无限循环

时间:2012-04-20 23:06:59

标签: java multithreading clojure slime swank

回应一些“潜在的答案”

  • 你应该将“中断”洒进你的线程

    我不编写我的代码,意图是一个漫长的进程/无限循环;只是在开发过程中,我意外地编写恰好是无限循环的代码,因此我无法事先计划将“检查线程是否被中断”放入代码中。

问题:

随着我越来越熟悉Java / Clojure / Swank和增量代码开发。我发现很容易意外地编写一个最终成为无限循环的clojure函数 - 然后运行它。然后继续,然后钉住JVM,导致我的笔记本电脑上的风扇旋转 - 基本上,我必须杀死整个JVM才能摆脱一个逃跑的线程。

现在,无论如何我能以某种方式安全地杀死这些clojure线程吗?我很清楚Thread.stop有各种不安全的后果(比如持有其他线程可能需要的锁等等) - 但是,这些是无限循环的 clojure 函数 - 和我在任何STM之外做它们 - 所以我想知道是否有办法安全地杀死这些线程。

谢谢!

4 个答案:

答案 0 :(得分:7)

我不认为存在完整的答案,尽管有一些不完整但仍然有用的事情要做:

  • 首先,我从repl中点击ctrl-c ctrl-c,这会杀死前景线程,这会导致99%的常见错误。
  • 然后,如果失败,我会去终端和kill命令。
  • 之后是M-x slime-quit-lispclojure-jack-in

答案 1 :(得分:2)

编写一个宏来创建这些循环怎么样?宏可以在循环步骤中注入代码以定期检查指示它退出循环的内容,就像在/ tmp上存在临时文件一样。所以基本上要退出无限循环,你只需要创建那个临时文件。

答案 2 :(得分:0)

理论上,正如评论中所提到的,这是一个真正解决的难题。

实际解决方案的最佳希望......

我在这里假设你想要一种更可靠和安全的方法来杀死和分析正在运行的clojure线程中的活动。 。 。为此,JPS是可行的方法,因为JPS监控所有Java进程,包括你在标准clojure中做的任何事情。

我总是使用JPS来做这种事情,因为它可以用来显示这个过程 特定java类的名称包含类名...能够知道 最初调用过程的类可以让您非常准确地了解"什么"你是 实际上是杀人。

doolittle-5:~ Jpeerindex$ jps -l
61133 jline.ConsoleRunner
58998 start.jar
61161 sun.tools.jps.Jps
51866 jline.ConsoleRunner

在这种情况下,因为" lein repl" (clojure repl)是通过jline(主要类)开始的 作为ConsoleRunner),我们可以这样看。

如果您确实需要查看详细信息,可以选择其中任何一个进程并使用jstack调用它们:

$> jstack 51866

  

"帮派工作人员#0(并行GC线程)" prio = 9 tid = 101802800   nid = 0x1017f9000 runnable

     

"帮派工作者#1(并行GC线程)" prio = 9 tid = 101803800   nid = 0x102301000 runnable

     

"并发Mark-Sweep GC线程" prio = 9 tid = 10184e000 nid = 0x1093f0000   可运行的" VM周期性任务线程" prio = 10 tid = 1018a4000   nid = 0x10a310000等待条件

     

" Exception Catcher Thread" prio = 10 tid = 101802000 nid = 0x100704000   可运行的JNI全球参考:137

在这种情况下,你能够感受到是否有任何真实的问题在你的线程中,准确地识别它们并自信地杀死它们等等......

答案 3 :(得分:0)

在Eclipse / Counterclockwise beta中,可以选择手动停止运行(失控)线程,而无需停止REPL。我喜欢这个功能,原因与你想拥有它一样。

它使用了NREPL 0.2.0 beta,我想通过clojure.tools.nrepl.middleware.interruptible-eval。不仅Eclipse / CCW NREPL 0.2.0客户端,而且最新版本的REPL-y应该支持此功能(默认CTRL-C用于停止线程,CTRL-D用于停止REPL)。