停止/杀死Java

时间:2016-12-21 06:46:38

标签: java multithreading

我正在编写一个程序,我从main函数调用多个线程。有一个For循环,它在循环中启动线程。 我想实现一个功能,如果在一个线程中发生某些异常,那么它应该停止所有当前正在运行/提交的线程,或者处于等待状态的线程。此外,不应再从循环中提交更多的线程。

P.S。我正在维护一个Map,它记录所有线程Map <threadName, Thread> 而且我没有使用执行服务。

如何杀死或停止所有线程,并防止在任何一个线程发生异常后提交更多线程。

4 个答案:

答案 0 :(得分:2)

请注意,没有“内置”功能可以在java中停止某个线程 - 某些方法确实存在,但所有方法都已弃用,因为如果正在运行的代码不合作,它们可能会造成麻烦。所以你的代码必须实现一些方法来基于某个标志退出run() - 方法,这必须在线程外部设置。如果你的帖子正在使用wait(),那么拨打interrupt()可能会派上用场。

答案 1 :(得分:2)

您无法在Java中强制停止线程。

是的,有Thread.stop()和相关的方法,但它们已被弃用多年for good reason

  

为什么Thread.stop已被弃用?
  因为它本质上是不安全的。停止线程会导致它解锁已锁定的所有监视器。 (当ThreadDeath异常向上传播时,监视器将被解锁。)如果先前受这些监视器保护的任何对象处于不一致状态,则其他线程现在可以以不一致的状态查看这些对象。据说这些物体已被损坏。当线程对受损对象进行操作时,可能会导致任意行为。这种行为可能很微妙并且难以检测,或者可能是明显的。与其他未经检查的异常不同,ThreadDeath会默默地杀死线程;因此,用户没有警告他的程序可能被破坏。腐败可以在实际损害发生后的任何时间显现,甚至在未来几小时或几天。

由于上述原因,您不应该使用这些方法,也不要依赖它们(许多使用线程繁重方法的API会很乐意忽略对stop()interrupt()的任何调用)。

一旦我们解决了这个问题,你仍然可以为你的线程实现逻辑,以便在你提出要求时尽快终止。

你需要做两件事:

1.-检查Thread.interrupted()方法中的run()。像这样:

@Override
public synchronized void run() {
    while (yourFinishCondition && !Thread.interrupted()) {
        // do stuff until you finish, or until the thread is interrupted from the outside
    }
}

2.-在主要方法的每个线程上调用interrupt(),以便在需要时发出终止信号,如下所示:

Thread.UncaughtExceptionHandler h = (thread, exception) -> {
    thread0.interrupt();
    thread1.interrupt();
    thread2.interrupt();
};

一点点PoC:

public class Main {

    static class MyThread extends Thread {
        public MyThread(String s) {
            super(s);
        }
        @Override
        public synchronized void run() {
            while(!Thread.interrupted()) {
                if (new Random().nextInt(1000000) == 7) {
                    throw new RuntimeException(Thread.currentThread().getName()+" oops!");
                }
            }
            System.out.println(Thread.currentThread().getName()+" interrupted");
        }
    }

    public static void main(String[] args) {
        final MyThread thread0 = new MyThread("thread0");
        final MyThread thread1 = new MyThread("thread1");
        final MyThread thread2 = new MyThread("thread2");

        Thread.UncaughtExceptionHandler h = (thread, exception) -> {
            System.out.println(exception.getMessage());
            thread0.interrupt();
            thread1.interrupt();
            thread2.interrupt();
        };
        thread0.setUncaughtExceptionHandler(h);
        thread1.setUncaughtExceptionHandler(h);
        thread2.setUncaughtExceptionHandler(h);

        thread0.start();
        thread1.start();
        thread2.start();
    }
}

输出:

thread2 oops!
thread1 interrupted
thread0 interrupted

进一步阅读:https://www.securecoding.cert.org/confluence/display/java/THI05-J.+Do+not+use+Thread.stop()+to+terminate+threads

答案 2 :(得分:0)

您可以编写代码来终止finally块或catch块中的所有正在运行的线程(可能不推荐使用)

在杀死所有正在运行的线程时,refer this thread

答案 3 :(得分:-1)

如果我问你的问题是正确的,你需要捕获异常并需要保持/维护列表作为共享对象,然后在其他线程上调用thread.stop()会解决问题吗?但是在最近的java版本中不推荐stop方法,所以你可以使用thread.yield()使线程释放CPU和其他资源,但它仍然不能保证线程的立即终止。