Java如何打破无限循环

3

我在生产环境中遇到了一个特殊的情况,其中一段代码陷入了无限循环。原因主要是数据相关的问题,无法找出真正的原因。同时,我希望能够生成一个单独的子线程来执行该代码段,并且如果它执行时间超过30秒,就希望停止该子线程的执行。

Thread t = new Thread() {
    public void run() {
                    // This is where i will the method that runs in a infinite loop
                    callMethodThatRunsInInfiniteLoop();
    };
};

t.start();
try {
    t.join(2000); // wait 2s
} catch (InterruptedException e) {
    e.printStackTrace();
} 

// if not completed how to break the child thread ???

2
如果你绝对必须这样做,你可以尝试使用Thread.stop,但你真的应该尝试利用中断 - obataku
Thread.stop() 已经被弃用了吧?在像 Jboss AS 7 这样的 Appserver 环境中使用它,会有什么问题吗?无法使用 interrupt,因为线程永远不会等待任何东西,并且导致无限循环的代码位于第三方库中,我无法修改。 - user807737
是的,这就是为什么我强调只有在被迫时才应该使用它。是的,它是 - obataku
4个回答

1

有没有一种方法可以通过抛出异常来使无限循环代码中断?例如,将某些变量设置为null?可能的好处是受影响的线程(如果编写得当)将在停止之前清理自己并更好地关闭。


很遗憾,这是第三方代码,我们无法轻易更改它。 - user807737

1
很遗憾,这是第三方代码,不容易进行更改。
听起来你正在尝试解决第三方库中的问题...或者是在调用第三方库时出现了错误输入等问题。
我的建议是解决那个问题,而不是试图终止错误线程。如果你无法做到这一点,那么你有两个选择:
1. 修改第三方库以使其具有中断感知/响应,并使用它来停止它。 2. 尝试找到一种方法“进入”第三方库的数据结构(例如使用反射),并导致其死亡。
如果你采取后者,那么也许你应该考虑在单独的JVM中运行第三方库,以便你可以使用进程API强制终止它。

话虽如此,但只有在极少数情况下使用Thread.stop()才是(可能)安全的。基本上,如果错误的线程不创建子线程,不与其他线程交互,不共享数据结构,并且在您终止它时不能进行类初始化,则您可能会安全。问题在于,有太多理论情况可以导致停止线程造成损坏,因此很难知道您是否考虑了所有这些情况。


+1 同意解决核心问题是最好的。利用令人讨厌的反射来强制进行丑陋的终止的想法不错。(是的,这变得非常非常粗糙了) 另一个 Thread.stop() 可能会有问题的情况是如果该线程正在获取锁或打开文件时,在写入或删除文件、打开流、套接字等过程中。换句话说,Thread.stop() 很少是安全的! - user949300
感谢您的建议。导致第三方API进入循环的原因是由于一些错误的输入,可能听起来有点滑稽,它在尝试使用Exception的toString()构造错误消息时进入了循环。如果我能确定问题所在,我很乐意修复代码或输入(只是输入太多了)。这是一个难以重现的问题,到目前为止只发生了两次。上述逻辑是为了在发生问题时识别问题。我已经采用了Thread.stop(),希望这是一个短期解决方案,如veer所建议的。 - user807737

0
根据方法的实现方式,你可以在独立的JVM中启动它,然后通过调用destroy()方法来停止进程。
Process process = new ProcessBuilder("java", "-cp", "/some/class/path", "com.mycompany.MyLauncher").start();

// sometime later
process.destroy();

0

所有纯外部停止线程的方法都已被弃用并被认为是不安全的。唯一安全停止线程的方法需要:

  1. 修改正在运行的代码,检查是否已通过设置某个stopMe变量礼貌地请求停止;或者
  2. 利用另一个线程已经使用的变量来导致线程退出(这通常是非常糟糕的做法);例如,通过强制它抛出异常,如用户949300所建议的那样。

如果没有这样做,你别无选择,只能使用不安全的方法,也就是Thread.stop(),这也是非常糟糕的做法。这是一个非常糟糕的想法,当然唯一的真正解决方案是要么改变你的输入,使其不发生这种情况,要么修复第三方代码。

线程正在使用的任何对象可能处于不一致(可能无法使用)的状态,因此尽量避免让线程修改任何重要的内容,并且如果可以的话不要查看任何输出变量。

Thread.stop()方法似乎仍然存在于Java SE 7中,虽然已被弃用,但我不能保证你的特定环境。

请参阅http://docs.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接