侧边栏壁纸
博主头像
翻斗

开始一件事最好是昨天,其次是现在

  • 累计撰写 44 篇文章
  • 累计创建 42 个标签
  • 累计收到 3 条评论

如何杀掉java线程

翻斗
2020-04-15 / 0 评论 / 0 点赞 / 750 阅读 / 2,104 字

Baeldung 翻译系列之Java并发基础:

Java中的concurrent包
Java中的Synchronized关键字
Future介绍
ThreadLocal介绍
Java线程的生命周期
如何杀掉一个Java线程
Java中的线程池介绍
实现Runnable接口还是继承Thread类
Java中的wait和notify方法
Runnable vs Callable
wait和sleep的区别
Thread.join方法介绍
Java中使用锁对象
ThreadPoolTaskExecutor中的corePoolSize和maxPoolSize
Java中的异步编程

1. 介绍

在这篇简短的文章中,我们将介绍如何在Java中停止一个线程 - 这并不简单,因为Thread.stop()方法已经被弃用。

Oracle的这个更新所解释的,stop()可能会导致监视的对象被破坏。

2. 使用一个标志位

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

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

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 
         } 
    } 
}

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

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

3. 中断一个线程

sleep() 设置为一个很长的时间,或者我们正在等待一个可能永远不会被释放的锁时,会发生什么?

我们面临的风险是阻塞时间过长或者永远无法干净地终止。

我们可以为这些情况创建 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);
    }
}

我们添加了一个 interrupt() 方法,它将 running 标志设置为 false,并调用 worker 线程的 interrupt() 方法。

如果在调用此方法时线程正在睡眠,sleep() 将会因 InterruptedException 退出,任何其他的阻塞调用也会如此。

这将线程返回到循环中,由于 runningfalse,所以它将退出。

4. 总结

在这个简明教程中,我们研究了如何使用原子变量,可选地结合调用 interrupt(),来干净地关闭一个线程。这肯定比调用已经被弃用的 stop() 方法并冒着永久锁定和内存损坏的风险要好。

和往常一样,完整的源代码可以在 GitHub 或者 Gitee 上找到。

0

评论区