How to Kill a Java Thread – 如何杀死一个Java线程

最后修改: 2017年 11月 26日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

In this brief article, we’ll cover stopping a Thread in Java – which is not that simple since the Thread.stop() method is deprecated.

在这篇简短的文章中,我们将介绍在Java中停止一个Thread–这并不那么简单,因为Thread.stop()方法已经废弃了。

As explained in this update from Oracle, stop() can lead to monitored objects being corrupted.

正如Oracle的这个更新中所解释的那样, stop()可能导致监控对象被破坏。

2. Using a Flag

2.使用旗帜

Let’s start with a class that creates and starts a thread. This task won’t end on its own, so we need some way of stopping that thread.

让我们从一个创建并启动一个线程的类开始。这个任务不会自己结束,所以我们需要一些方法来停止这个线程。

We’ll use an atomic flag for that:

我们将使用一个原子标志来实现这一点。

public class ControlSubThread implements Runnable {

    private Thread worker;
    private final AtomicBoolean running = new AtomicBoolean(false);
    private int interval;

    public ControlSubThread(int sleepInterval) {
        interval = sleepInterval;
    }
 
    public void start() {
        worker = new Thread(this);
        worker.start();
    }
 
    public void stop() {
        running.set(false);
    }

    public void run() { 
        running.set(true);
        while (running.get()) {
            try { 
                Thread.sleep(interval); 
            } catch (InterruptedException e){ 
                Thread.currentThread().interrupt();
                System.out.println(
                  "Thread was interrupted, Failed to complete operation");
            }
            // do something here 
         } 
    } 
}

Rather than having a while loop evaluating a constant true, we’re using an AtomicBoolean and now we can start/stop execution by setting it to true/false.

我们没有使用while循环来评估一个常数true,而是使用一个AtomicBoolean,现在我们可以通过将其设置为true/false来开始/停止执行。

As explained in our introduction to Atomic Variables, using an AtomicBoolean prevents conflicts in setting and checking the variable from different threads.

正如我们在原子变量介绍中所解释的那样,使用AtomicBoolean可以防止不同线程在设置和检查变量时的冲突。

3. Interrupting a Thread

3.中断一个线程

What happens when sleep() is set to a long interval, or if we’re waiting for a lock that might never be released?

sleep()被设置为一个很长的时间间隔,或者我们在等待一个时,会发生什么?

We face the risk of blocking for a long period or never terminating cleanly.

我们面临着长期阻断或从未干净地终止的风险。

We can create the interrupt() for these situations, let’s add a few methods and a new flag to the class:

我们可以为这些情况创建interrupt(),让我们为该类添加几个方法和一个新的标志。

public class ControlSubThread implements Runnable {

    private Thread worker;
    private AtomicBoolean running = new AtomicBoolean(false);
    private int interval;

    // ...

    public void interrupt() {
        running.set(false);
        worker.interrupt();
    }

    boolean isRunning() {
        return running.get();
    }

    boolean isStopped() {
        return stopped.get();
    }

    public void run() {
        running.set(true);
        stopped.set(false);
        while (running.get()) {
            try {
                Thread.sleep(interval);
            } catch (InterruptedException e){
                Thread.currentThread().interrupt();
                System.out.println(
                  "Thread was interrupted, Failed to complete operation");
            }
            // do something
        }
        stopped.set(true);
    }
}

We’ve added an interrupt() method that sets our running flag to false and calls the worker thread’s interrupt() method.

我们添加了一个interrupt()方法,将我们的running标志设为假,并调用工作线程的interrupt()方法。

If the thread is sleeping when this is called, sleep() will exit with an InterruptedException, as would any other blocking call.

如果在调用时线程正在睡觉,sleep()将以InterruptedException>退出,如同其他阻塞调用一样。

This returns the thread to the loop, and it will exit since running is false.

这就把线程返回到循环中,由于running是假的,它将退出。

4. Conclusion

4.结论

In this quick tutorial, we looked at how to use an atomic variable, optionally combined with a call to interrupt(), to cleanly shut down a thread. This is definitely preferable to calling the deprecated stop() method and risking locking forever and memory corruption.

在这个快速教程中,我们研究了如何使用一个原子变量,再加上对interrupt()的调用,干净地关闭一个线程。这绝对比调用被废弃的stop()方法和冒着永远锁定和内存损坏的风险要好。

As always, the full source code is available over on GitHub.

一如既往,完整的源代码可在GitHub上获得