【问题标题】:Stopping a thread that could be looping forever停止可能永远循环的线程
【发布时间】:2011-08-22 19:37:34
【问题描述】:

我有一个程序,我将用户键入的 java 代码编译到文本字段中,然后运行它。 A 在单独的线程中运行代码,这样他们用来输入源代码的 GUI 就不会被锁定。

GUI 有一个应该停止线程的中止按钮。我的问题是,无论编译线程内部发生什么,我都需要停止编译线程,这意味着我必须考虑线程陷入无限循环(由于用户错误)并且无法正确结束的情况本身使用安全标志。我已经阅读了许多涉及使用某种标志的解决方案,但由于这个循环问题,我无法使用它们。我需要停止线程并释放它正在使用的内存(我不能让它永远坐在后台,除非那是唯一剩下的解决方案)。有什么建议或替代解决方案吗?希望一些新的观点可以帮助解决这个问题。

编辑:

这是用户提交的代码示例:

public class RunMe extends SomethingThatRuns {
    public void run() {
        int i = 0;
        while (i = 0) {
            //Prepare to get stuck!
        }
    }
}

我将编译这个类,然后运行它。这就是它会卡住的地方,run() 方法永远无法完成,甚至循环检查标志。

【问题讨论】:

  • 我觉得你需要有自己的接口来实现它们。正确的方法是使用Thread.interrupt(),但如果代码不尊重该标志,那么您将陷入循环。我想知道其他人是怎么想的?我很乐意提供一个示例界面。
  • 你必须使用线程吗?您可以在单独的过程中进行编译吗?然后如果运行时间过长,你可以kill这个进程。
  • 你为什么不发布一些代码?这将使我们更容易排除故障。
  • 是否可以在调试器中运行代码?这可能会提供随时中断它的选项..

标签: java multithreading swing


【解决方案1】:

你可以在一个新的 JVM 中运行它,这样你就可以在你想要的时候杀死它。 考虑到安全性,这也可能是一件好事。

【讨论】:

  • 它与程序的其余部分交互,所以它必须在同一个JVM中。此外,在此特定应用程序中,安全性不是问题。
  • 同意这个解决方案。不过,进程间通信不会很有趣。
  • 在和我的一些同事讨论了整件事之后,这就是我要说服的解决方案。
  • @toriscope 你是如何进行沟通的?你有一些关于如何在不同的 JVM 中运行代码的示例代码
【解决方案2】:

在线程上调用stop()

是的,这是一种已弃用的方法。但是,它真的不应该被“弃用”,而应该是“危险的”。然而,在某些情况下,除了使用它之外别无选择,而调用用户提供的“代理”就是其中一种情况。

确保您的程序不使用由该用户线程操作的任何数据;或者,如果你这样做了,设计一些事务机制来在线程之间安全地交换数据。

即使这种方法也不能保证终止线程。例如,用户可以捕获生成的Throwable 并忽略它。或者,如果线程在某些本机代码中,则线程实现可能不会响应 stop() 调用。但这是你最好的机会。

【讨论】:

    【解决方案3】:

    这里的核心问题是代码甚至允许输入无限循环作为用户错误的一部分。解决这个问题,其他一切都会变得更容易处理。

    正常运行的线程通常应该在没有工作可做时优雅地终止自己(或者如果这是您的应用程序的设计,则安静地返回线程池以请求更多工作)。如果你觉得你需要让一个线程强行杀死另一个线程,那么你可能遇到了一个基本的设计问题。让一个线程告诉另一个线程很好,“嘿,你现在应该终止,这样我就可以和你一起加入......”,因为这样可以让你的线程在完成时清理它们。强行销毁线程并不是处理这些情况的正确方法。

    【讨论】:

    • 为了将权力掌握在用户手中,我们必须考虑到用户进入了一个永无止境的循环。他们的代码在线程中运行的事实对他们来说应该是不可见的。
    • 如何检查代码是否存在无限循环(参见“停止问题”)?
    • 啊哈,我错过了可以运行的第 3 方代码的部分。在这种情况下,使用单独的 JVM 来运行代码的公认答案更合适,因为这样您就可以隔离用户代码的影响并使用启发式方法来确定是否/何时终止他们的失控进程。您是否还可以做一个简化的假设,即如果用户编写了一个无限循环,它是在他们自己的头脑中,并且应该由他们来解决这个问题?不了解您的系统,很难猜测这是否适合您。
    【解决方案4】:

    您可以使用它们在每个循环中插入中断检查,也可以在其他地方插入。

    我可以看到两个选项:

    • 在编译用户代码时,您可以在之前对其进行编辑。您可以使用 ANTLR 来解析和修改代码。
    • 有像 ASM 这样的字节码操作框架允许您操作已经存在的代码 编译。

    我认为这并不容易,但它可能是一种方法。

    【讨论】:

      【解决方案5】:

      interupt(); gui 中的线程

      并且在线程定期运行的代码中检查Thread.interrupted(),并在您特别是在循环内部进行检查时抛出异常

      【讨论】:

      • 啊,我很想这样做,但我不能,因为用户将编写实际运行的代码,而不是我。
      • @any 告诉用户定期检查中断状态,不是万无一失但很少运行用户代码
      【解决方案6】:

      从高层次上讲,您是在问一个线程如何停止另一个线程。为此,请参阅此 SO 问题Stopping a Thread in Java?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-09-02
        • 2017-05-02
        • 2018-08-14
        • 1970-01-01
        • 2012-03-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多