【问题标题】:killing a java thread in test在测试中杀死一个java线程
【发布时间】:2016-12-19 15:32:46
【问题描述】:

我正在编写一种关于编程的教程(它将是 github 上的 Java 存储库),用户可以在其中克隆存储库并在空方法中编写自己的代码来解决算法问题。在他们编写完代码后,他们可以启动单元测试来检查他们的解决方案是否正确以及它是否在一定时间内完成执行(以确保他们找到了最有效的解决方案)。 所以我的 repo 将包含许多带有空方法的类和所有非空单元测试,以检查用户将编写的代码。

我在 JUnit 测试中所做的事情是这样的:

// Problem.solveProblem() can be a long running task
Thread runner = new Thread(() -> Problem.solveProblem(input)); 

runner.start();

try {
    Thread.currentThread().sleep(500);
}
catch (InterruptedException e) {
    e.printStackTrace();
}

if (runner.isAlive()) {
    fail("Your algorithm is taking too long.");
    runner.stop();
}

现在,如果用户编写了未优化的算法,测试会正确失败,但runner 线程将继续运行(测试线程也会如此)直到它终止,这可能会在几分钟后发生,尽管我致电running.stop()。所以我的测试可以持续几分钟而不是我想要的几秒钟。

我知道如何优雅地终止 Java 中的线程,但在这种情况下,我不希望用户处理多线程问题(例如检查/更新共享变量):我只希望他们只编写代码解决问题。

所以我的问题是:有没有办法突然杀死 Java 中的线程?如果没有,我还有其他方法可以实现我的目标吗?

谢谢, 安德烈亚

【问题讨论】:

  • 如果每个单元测试都运行在一个新的JVM中,你可以将用户的线程设置为守护线程。这应该让JVM立即退出。
  • 如果我理解正确的话,守护线程是当没有其他用户线程在运行时被 JVM 立即杀死的线程。我已将线程运行器设置为守护进程,但用户线程(JUnit 测试)在关闭 JVM 之前仍等待其终止。也许我不明白守护线程是如何工作的?
  • 第一件事是调用 stop 方法,因为它已被弃用,并且您在文档中被警告不要使用它。第二件事是,正如我所说,只有当 JUnit 在自己的 JVM 中运行并在完成时退出时,这才会起作用。如果主线程终止,而所有其他线程都是守护线程,则 JVM 将终止。

标签: java multithreading junit


【解决方案1】:

您可以使用 ScheduledExecutorService 来设置超时:

ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); 
Future<?> future = executor.schedule(() -> Problem.solveProblem(input));
try {
    future.get(500, TimeUnit.MILLISECONDS);
} catch (Exception e){
    fail("Your algorithm is taking too long.");
    future.cancel(true);
}

可能需要一些改进,但您会掌握基本知识。

【讨论】:

  • future.cancel() 似乎不起作用:测试的行为和以前一样,它只是等到未来执行结束后再结束测试。
  • 您可以强制关闭执行器。
  • ExecutorService.shutdown() 不会导致当前任务终止。 ExecutorService.shutdownNow() 无法保证成功,因为它使用 Thread.interrupt 尝试中断线程。
  • 这就是我的意思。此处不完全可用
【解决方案2】:

使用Thread.currentThread().getThreadGroup() 进行迭代。 Thread.stop 是蛮力的方式,但在你的情况下,如果你调用 Thread.interrupt -edit- 我读得太快了,以为你在生成的线程中调用 sleep 可能会起作用。重读,我看到你只是在你的主线程中这样做,所以正如 RealSkeptic 在这篇文章中评论的那样,interrupt 可能不太可能解决这个问题

【讨论】:

  • 为什么interrput 会起作用?如果线程不在可中断操作中,则仅设置中断标志。 stop 已被弃用。
  • 正在创建的线程(至少在本例中)正在调用睡眠,该中断将唤醒 - 检查一下,它只是主线程。所以在这种情况下中断不起作用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
  • 2013-08-04
  • 2012-09-14
  • 1970-01-01
相关资源
最近更新 更多