22

我正在使用 Windows 7 操作系统。我的应用程序中有6线程。为了测试警报以检查线程的健康状况,我需要手动终止线程并检查警报是否正常工作。我们可以像杀死一个进程一样杀死一个线程pid吗?

4

8 回答 8

37

Dan Woods 在此博客条目中记录了如何杀死线程... https://web.archive.org/web/20160302023213/http://www.rhcedan.com/2010/06/22/killing-a-java -thread 他执行的步骤涉及使用调试器 (JDB) 并在线程执行中注入异常。具体来说...

  1. 确保使用以下参数启动您的 java 程序:

    -Dcom.sun.management.jmxremote.port=50199
    -Dcom.sun.management.jmxremote.authenticate=false
    -Dcom.sun.management.jmxremote.ssl=false
    -Xrunjdwp:transport=dt_socket,address=50100,server=y ,暂停=n

    这将允许我们在确定是哪个线程导致问题后,将 java 调试器附加到正在运行的进程。此外,请确保您正确设置了 iptables,以便仅允许来自您管理的主机/工作站的 50100 和 50199 连接。

  2. 识别有问题的线程:
  3. 杀死线程。在此示例中,ThreadName 为“btpool0-0?”。启动 java 调试器(也随 JDK 发行版一起提供),并附加到正在运行的 JVM……</p>

    [root@host ~]# jdb -attach 50100

获取一个正在运行的线程列表——这也会给我们 JVM 看到的线程 id:

> threads  
--snip--  
(org.mortbay.thread.BoundedThreadPool$PoolThread)0x25cb
btpool0-0 running  
--snip--

我们要杀死的线程 id 是“0x25cb”。杀死线程的第一步是跳进去,然后挂起……</p>

thread 0x25cb
btpool0-0[1] suspend 0x25cb
btpool0-0[1] step
Step completed: <... snip ...>
btpool0-0[1] kill 0x25cb new java.lang.Exception()
killing thread: btpool0-0
btpool0-0[1] instance of 
com.site.package.name(name='btpool0-0', id=9675) killed btpool0-0[1]

退出java调试器,你就完成了!

于 2013-04-09T19:46:31.540 回答
14

没有安全的方法来“杀死”一个线程而不杀死它所在的进程。这不是你会故意做的事情。出于测试目的,我会在您的应用程序中添加代码来支持这一点。

于 2012-07-23T10:42:11.503 回答
9

这不是真的。如果您知道线程 ID,您始终可以使用 GDB 附加到 JVM 进程并调用 pthread_kill。您只需要从 java 线程转储(执行 kill -3)进行翻译,它会为您提供一个十六进制 id(本机 id),然后查看 GDB 中的线程列表(信息线程)并找到真正的线程 id。

这被证明是有效的。

于 2015-04-09T22:24:52.567 回答
4

正如彼得所说,你不能安全地做到这一点。确实在某些平台Thread.kill上甚至没有实现。然而:

  • 如果这只是为了测试,那么调用的单元测试Thread.kill是合理的……假设它在需要工作的测试平台上工作。(源代码中的“大声”注释是为了帮助人们移植单元测试......)

  • 另一种选择是向可运行线程添加一些代码,允许您的单元测试告诉它死亡。如果线程代码需要(几乎)是生产代码才能工作,您可以创建一个覆盖某些内容的子类,以便它以适合您目的的方式“中断”......用于测试。事实上,这种方法允许您以受控方式“中断”线程,从而可能允许您测试警报代码的不同方面。

于 2012-07-23T11:31:43.603 回答
2

您不能从外部(操作系统或调试器)执行此操作,您必须编写自己的线程看门狗,它可以与用户交互并杀死您想要的线程。

尝试在这里查看如何使用 java 处理信号

于 2012-07-23T10:44:16.940 回答
0

在线程中等待一段时间并在代码中终止线程 - 简单的方法。

于 2012-07-23T10:48:31.777 回答
0

在java中你不能杀死喜欢的unix。您可以interrupt在 java 中执行,也可以在 unix 中终止进程。

于 2012-07-23T10:44:28.737 回答
0

正如之前buzz3791的帖子中所提到的,它使用jdb 工作。然而我注意到的变化是,你不能杀死线程,但你可以中断或挂起线程。

#jdb -附加 50100

线程——这将显示在组和引用处理程序部分下的 jvm 上运行的所有线程。

团体 引用处理程序
:(com.orienttechnologies.orient.server.network.protocol.binary.ONetworkProtocolBinary)0x36c1: OrientDB (/xxx.xxx.xxx.xxx:123) <- BinaryClient (/xxx.xxx.xxx.xxx:678)

线程 0x36c1——这将是线程 ID,可以从您希望杀死/中断的线程中的一个线程中选取并运行此中断 0x36c1

OrientDB (/xxx.xxx.xxx.xxx:123) <- BinaryClient (/xxx.xxx.xxx.xxx:678)[1]中断 0x36c1

您可以多次尝试相同的中断命令,如果已经中断,则会显示线程 id 无效。因此您知道线程已被杀死,这可以通过查看堆栈跟踪来验证并确认。

使用 jdk 8 在 OrientDB 数据库服务器上对此进行了测试,并且可以正常工作。

于 2021-01-12T06:29:21.777 回答