如何在java中以快速干净的方式中止线程?

2022-09-01 14:31:09

这是我的问题:我有一个对话框,其中包含一些用户可以更改的参数(例如通过微调器)。每次更改其中一个参数时,我都会启动一个线程以根据新参数值更新3D视图。如果用户在第一个线程工作时更改了另一个值(或通过多次单击微调器箭头再次更改相同的值),则我想中止第一个线程(以及3D视图的更新)并使用最新的参数值启动一个新线程。

我该怎么做?

PS:我的线程方法中没有循环,因此检查标志不是一个选项:更新3D视图的线程基本上只调用一个执行时间很长的方法。我无法在此方法中添加任何要求中止的标志,因为我无法访问其代码。run()


答案 1

尝试中断(),正如有些人所说,看看它是否对你的线程有任何影响。如果没有,请尝试销毁或关闭将使线程停止的资源。这有可能比试图向它投掷Thread.stop()好一点。

如果性能可以容忍,您可以将每个3D更新视为离散的不可中断事件,然后让它运行到结论,然后检查是否有新的最新更新要执行。这可能会使 GUI 对用户来说有点不稳定,因为他们可以进行五次更改,然后查看五次更改前的图形结果,然后查看其最新更改的结果。但根据此过程的长度,它可能是可以容忍的,并且可以避免必须杀死线程。设计可能如下所示:

boolean stopFlag = false;
Object[] latestArgs = null;

public void run() {
  while (!stopFlag) {
    if (latestArgs != null) {
      Object[] args = latestArgs;
      latestArgs = null;
      perform3dUpdate(args);
    } else {
      Thread.sleep(500);
    }
  }
}

public void endThread() {
  stopFlag = true;
}

public void updateSettings(Object[] args) {
  latestArgs = args;
}

答案 2

更新 3D 视图的线程应定期检查某些标志(使用 a ),以查看它是否应该终止。当您想要中止线程时,只需设置标志即可。当线程下次检查该标志时,它应该简单地中断它用于更新视图并从其方法返回的任何循环。volatile booleanrun

如果您确实无法访问线程正在运行的代码以使其检查标志,则没有安全的方法来停止线程。在应用程序完成之前,此线程是否曾经正常终止?如果是这样,是什么原因导致它停止?

如果它运行了很长一段时间,并且您只需要结束它,则可以考虑使用已弃用的方法。但是,它被弃用是有充分理由的。如果该线程在某个操作过程中停止,该操作使某些内容处于不一致状态或某些资源未正确清理,那么您可能会遇到麻烦。以下是文档中的说明:Thread.stop()

此方法本质上是不安全的。使用 Thread.stop 停止线程会导致它解锁所有已锁定的监视器(这是未经检查的 ThreadDeath 异常向上传播堆栈的自然结果)。如果以前受这些监视器保护的任何对象处于不一致状态,则损坏的对象对其他线程可见,这可能会导致任意行为。stop 的许多用法应该替换为代码,这些代码只是修改某些变量以指示目标线程应停止运行。目标线程应定期检查此变量,如果该变量指示它要停止运行,则以有序的方式从其 run 方法返回。如果目标线程等待很长时间(例如,在条件变量上),则应使用中断方法来中断等待。有关详细信息,请参阅为什么 Thread.stop、Thread.suspend 和 Thread.resume 已弃用?