6

对一些“潜在答案”的回应

  • 你应该在你的线程中加入“中断”

    我编写代码的目的不是为了让它成为一个漫长的过程/无限循环;只是在开发中,我不小心编写了恰好是无限循环的代码,因此我永远无法事先计划将“检查线程是否被中断”放入代码中。

问题:

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

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

谢谢!

4

4 回答 4

8

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

  • 首先,我ctrl-c ctrl-c从 repl 中命中,它杀死了我 99% 的常见错误的前台线程。
  • 然后,如果失败,我会选择终端和kill命令。
  • 在那之后M-x slime-quit-lispclojure-jack-in
于 2012-04-21T01:06:46.220 回答
2

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

于 2012-04-21T06:24:31.623 回答
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

“Gang worker#0(并行 GC 线程)”prio=9 tid=101802800 nid=0x1017f9000 可运行

“Gang worker#1(并行 GC 线程)”prio=9 tid=101803800 nid=0x102301000 可运行

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

“异常捕获线程”prio=10 tid=101802000 nid=0x100704000 可运行 JNI 全局引用:137

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

于 2012-04-21T03:44:14.103 回答
0

在 Eclipse/逆时针测试版中,有一个选项可以手动停止运行(失控)线程,而无需停止 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)。

于 2012-04-21T12:19:31.260 回答