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

时间:2013-03-25 20:38:29

标签: java multithreading osgi

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

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

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

下一步该怎么做才能停止所有正在运行的线程?

我想要停止这些线程的原因是我需要将此项目作为捆绑包部署到OSGi容器。捆绑包启动后,多个线程将永远运行。所以我需要实现一个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(); 
}

3 个答案:

答案 0 :(得分:21)

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

  

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

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

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

此外,要认识到运行循环的代码是本身在一个线程中 - 这意味着你的循环可以很好地自杀,让所有其他线程都在运行。

答案 1 :(得分:1)

我使用了这段代码:

package com.xxx;

import com.xxx.tools.messageLog;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Mostafa Nazari
 */
public class ProcessAgent extends Thread{

    public ProcessAgent() {
        super("Process-Agent");
    }


    @Override
    public void run() {
        try {
            com.xxx.Process.agent.Main.main(new String[]{});
        } catch (Exception ex) {
            if (ex instanceof InterruptedException) {
                messageLog.stdwar("Process Agent Stopped");
            }else {
                messageLog.stderr("FATAL Error: "+ex.getMessage());
                Logger.getLogger(ProcessAgent.class.getName()).log(Level.SEVERE, null, ex);            
            }
        }    
    }

    public void terminate() {
        if (super.isAlive()) {
            ThreadGroup group = super.getThreadGroup();
            while (group != null) {
                group .interrupt();
                group = super.getThreadGroup();
            }
            super.interrupt();
        }
    }

    public String getStatus() {
        if (super.isAlive()) {
            return "running";
        } else {
            if (super.isInterrupted()) 
                return "stopping";
            else
                return "stopped";
        }
    }

}

希望它对这个问题有用

答案 2 :(得分:0)

使用高级concurrent API,例如ExecutorServiceThreadPoolExecutor

,而不是创建普通的Thread

您可以在这篇文章中查看不同的API:

Java's Fork/Join vs ExecutorService - when to use which?

请参阅以下有关强制关闭ExecutorService的SE问题:

How to forcefully shutdown java ExecutorService

相关问题