2012-07-23 72 views
17

我使用Windows 7操作系统。我的应用程序中有大约6线程。为了测试警报以检查线程的健康状况,我需要手动终止线程并检查警报是否正常工作。我们能否杀死一个线程,就像我们如何用pid杀死一个进程?如何使用VisualVM或使用unix命令杀死Java线程?

+2

线程是应用程序的内部实现细节它们不可见或可从应用程序外部访问。如果线程意外死亡,则应用程序不可用,因为线程之间没有隔离。 (想想如果线程锁定会发生什么,如果释放它,繁荣,如果你不释放它,繁荣。) – 2012-07-23 10:48:10

回答

11

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

+0

感谢Peter Lawrey。 – Arun 2012-07-23 10:48:23

+0

但是不推荐使用Thread.stop。我发现这很有用。 http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html – Arun 2012-07-23 10:49:16

+1

这就是为什么我说'没有安全的方法来“杀死”一个线程'这不阻止您将其用于测试目的。 – 2012-07-23 11:04:32

2

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

尽量显得是一个here如何与Java

0

处理信号在java中你不能杀了类似Unix的。你可以在java中使用interrupt或者你可以在unix中终止进程。

0

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

+0

我不认为你理解这个问题,无论如何,正如Peter Lawrey所说,没有安全的方法来杀死Java线程。 – 2012-07-23 11:23:26

+0

@StephenC抛出异常? – Mohan 2012-07-23 12:34:17

+0

你不能让一个不合作的线程抛出异常。这不是告诉线程“自杀”。它是关于杀死一个不在监听的线程......并以*模拟生产中的应用程序失败的方式进行。 – 2012-07-24 01:14:03

4

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

  • 如果这是只是为了测试,那个叫Thread.kill将是合理的单元测试...假设它的工作在哪里,它需要的工作测试平台。 (源代码中的“响亮”评论将帮助人们移植单元测试...)

  • 另一种替代方法是向线程runnable添加一些代码,以允许单元测试告诉它死。如果线程代码需要(几乎)生产代码才能工作,那么可以创建一个覆盖某些东西的子类,以便以适合您的目的的方式“打破”测试。实际上,这种方法允许您以受控方式导致线程“中断”,可能允许您测试警报代码的不同方面。

31

丹伍兹记录如何杀死这个博客条目线程... 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 =假
    -Dcom.sun.management.jmxremote.ssl =假
    -Xrunjdwp:交通= dt_socket,地址= 50100,服务器= Y,暂停= N

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

  2. 确定有问题的线程:
  3. 杀死线程。在这个例子中,ThreadName是“btpool0-0?”。火起来的Java调试器(也随JDK分布),并连接到运行的JVM ...

    [根@主机〜]#加多宝-attach 50100

获取列表正在运行的线程的 - 这也将给我们的线程ID作为JVM看到它:

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

,我们会杀了线程ID是“0x25cb”。杀死线程的第一步是跳到它,并暂停它...

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调试器,你就完成了!

+2

还有命令:interrupt [threadid] – revo 2013-08-27 09:30:23

2

这是不正确的。您可以随时使用GDB连接到JVM进程,如果知道线程ID,则可以调用pthread_kill。你只需要从java线程转储(做一个kill -3),它​​给你一个十六进制id(native id),然后查看GDB(信息线程)中的线程列表并找到真正的线程ID。

这被证明是可行的。