java - 如何找到并停止所有当前正在运行的线程?

标签 java multithreading osgi

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

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

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

下一步要做什么来停止所有正在运行的线程?

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

怎么样

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(); 
}

最佳答案

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

This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. If the target thread waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait.

从根本上说,线程需要构建和设计为安全终止,安全地杀死任意线程是不可能的。一个相当标准的模式是这样实现的:

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();
}

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

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


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

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

此外,要认识到运行循环的代码本身在一个线程中 - 这意味着您的循环很可能首先终止自身,让所有其他线程继续运行。

关于java - 如何找到并停止所有当前正在运行的线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15624296/

相关文章:

java - 使用PhP在android和mysql之间建立连接时出错

新手Java——死锁模仿

OSGI Felix 不导出 src/main/resource 文件

osgi blueprint如何读取bundle中的资源文件

java - 在任何情况下,Java都能比C++更快吗?

java - 为什么 grails 不能在同一个端口上运行两个应用程序?

multithreading - 创建一个将一直阻塞直到被n/2个以上线程调用的函数(伪代码)

java - 按属性搜索 OSGI 服务

java - 使用 java 从本地主机在远程 hdfs 上创建目录

python - Flask-socketio 在后台线程中复制文件时丢失事件