【问题标题】:Kill a Java Thread without looping在不循环的情况下终止 Java 线程
【发布时间】:2018-12-31 15:09:41
【问题描述】:

我在我的项目中使用了一个外部库(Generex),一个构造函数可能需要很长时间才能执行,所以我想有一个超时(比如说 50 毫秒),并且能够知道是否已达到超时。

所以我在考虑使用专用线程,并编写了以下代码:

@Test
public void isComputable() throws InterruptedException {
    for (int i=0; i<10;i++)
        System.out.println(check());

    Thread.sleep(300000);
}

private static boolean check() {

    final Thread stuffToDo = new Thread(() -> {while(true){}});

    final ExecutorService executor = Executors.newSingleThreadExecutor();
    final Future future = executor.submit(stuffToDo);
    executor.shutdown();

    try {
        future.get(50, TimeUnit.MILLISECONDS);
    }
    catch (InterruptedException | ExecutionException | TimeoutException ie) {
        stuffToDo.interrupt();
        stuffToDo.stop();
        return false;
    }
    if (!executor.isTerminated())
        executor.shutdownNow();
    return true;
}

我用 while(true) 循环替换了对外部库的调用,但重要的是要注意,在我的情况下,我不能使用循环来检查线程是否被中断.

执行此代码时,每次调用 50 毫秒后我都得到了很好的答案,但线程没有被破坏,并且 CPU 使用率很高,正如我们在 JProfiler 中看到的那样(注意测试 i 只是为了有一个更好的图表):

请问有人知道如何解决这个问题吗?

注意:我知道我不应该使用已弃用的停止方法,我只是尝试了我所知道的一切来杀死线程。

【问题讨论】:

  • stop 方法不仅被弃用了。使用起来很危险(使资源处于不可预测的状态)。不要使用它。不要说“也许我还是会这样做”。将stop 视为从未存在过。无论如何,您必须以可以中断的方式编写长方法。如果没有 - 你不能打断它。
  • 问题是我无法访问这个长方法,它在依赖中
  • 你应该检查为什么构造函数需要很长时间。是每个使用它的人都需要很长时间,还是仅用于您自己的用例?它总是需要很长时间还是取决于输入?您是否必须每次都构造一个新对象,或者构造一个或一组对象会起作用,因此时间不再重要了?
  • 这是 lib 的一个已知问题:github.com/mifmif/Generex/issues/43 我想通过中断这个构造函数来避免这个问题
  • 好吧,这种方法真的行不通。你可以让它在后台继续运行,同时做其他事情;或者您可以研究您正在使用的正则表达式并尝试找到一个不会导致它花费很长时间的替代方法;或者您可以自己获取源并添加中断功能。该项目似乎已被放弃,否则我会说咨询作者。

标签: java timeout kill


【解决方案1】:

您要么必须定期检查代码 callex 中的中断,要么必须在另一个进程中运行代码。这些是您可以中断或终止运行代码的进程的唯一方法。

我建议对长时间运行的线程进行堆栈跟踪,以帮助将来修复它。

【讨论】:

    猜你喜欢
    • 2014-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-12
    • 1970-01-01
    相关资源
    最近更新 更多