当前位置: 首页 > 面试题库 >

如何查找和停止所有当前正在运行的线程?

葛玉堂
2023-03-14
问题内容

我有一个多线程的Java项目,我想添加一个方法stop()来停止所有正在运行的线程。问题在于该项目是由其他人开发的,而我不熟悉它如何实现多个线程。

我知道的是,一旦项目开始,就会调用许多线程,并且它们将永远运行。有没有办法找到所有正在运行的线程并停止它们?我进行了很多搜索,找到了如何获取正在运行的线程的列表:

Set<Thread> threadSet = Thread.getAllStackTraces().keySet();

接下来要停止所有正在运行的线程该怎么办?

我想停止这些线程的原因是,我需要将此项目作为一个捆绑包部署到OSGi容器。一旦捆绑包启动,多个线程将永远运行。因此,我需要实现destroy()方法来停止所有线程来控制包的生命周期。

怎么样

for (Thread t : Thread.getAllStackTraces().keySet()) 
{  if (t.getState()==Thread.State.RUNNABLE) 
     t.interrupt(); 
}

for (Thread t : Thread.getAllStackTraces().keySet()) 
{  if (t.getState()==Thread.State.RUNNABLE) 
     t.stop(); 
}

问题答案:

这是一个危险的想法。Javadoc的Thread.stop()解释如下:

这种方法本质上是不安全的。使用Thread.stop停止线程会导致它解锁所有已锁定的监视器(由于未经检查的ThreadDeath异常会自然传播堆栈)。如果先前由这些监视器保护的任何对象处于不一致状态,则损坏的对象将变为其他线程可见,从而可能导致任意行为。stop的许多用法应由仅修改某些变量以指示目标线程应停止运行的代码代替。目标线程应定期检查此变量,如果该变量指示要停止运行,则应有序地从其运行方法返回。如果目标线程等待很长时间(例如,在条件变量上),则应使用中断方法来中断等待。

从根本上讲,需要构建和设计线程以安全终止,因此无法安全地终止任意线程。一个相当标准的模式是这样实现的:

public abstract class StoppableRunnable implements Runnable {
    private volatile boolean stopWork;
    private boolean done;

    public final void run() {
        setup();
        while(!stopWork && !done) {
            doUnitOfWork();
        }
        cleanup();
    }

    /**
     * Safely instructs this thread to stop working,
     * letting it finish it's current unit of work,
     * then doing any necessary cleanup and terminating
     * the thread.  Notice that this does not guarentee
     * the thread will stop, as doUnitOfWork() could
     * block if not properly implemented.
     */
    public void stop() {
        stopWork = true;
    }

    protected void done() {
        done = true;
    }

    protected void setup() { }
    protected void cleanup() { }

    /**
     * Does as small a unit of work as can be defined
     * for this thread.  Once there is no more work to
     * be done, done() should be called.
     */
    protected abstract void doUnitOfWork();
}

您暗示您不是这些线程的作者,这表明它们可能无法安全地停止。在这种情况下,您可以html" target="_blank">调用Thread.interrupt()以指示线程停止其正在执行的操作(而不是上述模式,您可以使用Thread.interrupt()以达到类似的效果),但是类似地,如果线程的设计者没有编写它来处理中断,则可能不做任何事情或导致状态不一致或其他错误。

最终,Thread.stop()如果您只是想“
[强制]线程停止执行”而又不能修改线程的实现,那将是您想要的。但是,就像kill在Unix中使用一样,这是一个危险的提议,因此您应该以这种方式终止线程后,从根本上考虑JVM处于不稳定且不可修复的状态,然后尝试尽快退出该程序。

关于中断然后停止的建议:

这里仍然存在很多问题,特别是中断并不能保证线程会立即中断(它的工作方式与StoppableRunnable上面的类似,尽管不太明确),而是设置了一个标志,指出线程应尽可能地中断。这意味着您可以调用Thread.interrupt(),线程可以启动其正确的中断处理行为,然后中途进行调用,Thread.stop()引发火灾,猛烈杀死线程并可能破坏JVM。调用Thread.interrupt()不保证线程何时或如何响应该中断,这就是为什么我更喜欢中的显式行为StoppableRunnable。不用说,如果您要打电话Thread.stop(),先打电话几乎无济于事Thread.interrupt()。我不建议这样做,但您最好还是打电话Thread.stop()
首先。

此外,认识到运行循环的代码 本身就是线程中的 -这意味着循环很可能会先杀死自己,而使所有其他线程都运行。



 类似资料:
  • 我之所以要停止这些线程,是因为我需要将这个项目作为一个捆绑包部署到OSGi容器中。一旦包启动,多个线程将永远运行。因此,我需要实现一个destroy()方法来停止所有线程,以控制包的生命周期。 怎么样

  • 问题内容: 我从Linux Shell 连接到。我时不时地运行一个太大的查询。它可以打印,我已经知道这不是我的意思。我想停止查询。 击中(几次)会完全杀死并把我带回外壳,因此我必须重新连接。 是否可以在不杀死自己的情况下停止查询? 问题答案:

  • 问题内容: 如何以编程方式停止正在运行的mysql查询? 我面临的问题是查询是使用用户提供的数据构造的,并且偶尔可能需要很长时间才能执行(大型表15-3000万行)。我想为用户提供一个cancel- option,但不知道如何停止当前正在执行的mysql-query。 该应用程序是Java applet- servlet:用户在applet中指定条件,该条件将传递给servlet,在servlet

  • 问题内容: 简要描述;简介 将测试服务器重置为已知状态会导致我的测试失败,因为重置服务器时DataTables实例启动的Ajax请求正在进行中。我想通过在重置服务器之前停止DataTables请求来防止这种情况。 详细说明 我有一个在某些页面上使用DataTables的应用程序。这些数据表均执行服务器端查询以填充其表。 当我执行系统测试时,有时会发生争用情况: 测试运行程序启动测试服务器。 测试运

  • 问题内容: 这是执行程序类的方法: 在这里,它等待第二秒,但是当我运行代码时,它将引发异常: 我无法关闭中的并发线程破坏。这是我的代码流: 用Java执行程序类创建一个新线程来运行某些任务,即用 等待10秒以完成任务。 如果任务已完成,则可运行线程也将终止。 如果任务未在10秒内完成,则类应终止线程。 除了在最后一个场景中终止任务以外,其他所有操作都正常。我该怎么办? 问题答案: 该方法只是防止其

  • 问题内容: 我正在尝试制作一个简单的计时器,该计时器在指定的秒数后发出提示音。我设法使其正常工作,但是TimerTask在蜂鸣声后继续运行。现在我停止执行吗?这是我的代码: 问题答案: 您需要通过调用以下方法来取消计时器 这将取消任务,因此可以执行以下操作: