Java如何停止一个线程

Java如何停止一个线程

在Java中,停止一个正在运行的线程,我们可以通过如下方法实现:

  • 设置一个volatile类型的变量,通过判断变量的值来确定run方法是否运行完成正常退出
  • 通过interrupt()方法来通知,给线程打上一个终止的标志,但是具体的停止逻辑需要在线程内部实现

此外还有一种方法是调用stop()方法来停止线程,但是这个方法不安全:它会释放该线程持有的所有锁,一般任何进行加锁的代码块,都是为了保护数据的一致性,如果在调用thread.stop()后导致了该线程所持有的所有锁突然释放,那么被保护数据就有可能呈现不一致性,其他线程在使用这些被破坏的数据时,有可能导致一些很奇怪的应用程序错误。suspend方法:容易发生死锁,虽然调用suspend方法目标线程会停下来,但是仍然持有之前的锁,其他线程都不能访问锁定的资源,就会造成死锁,除非被挂起的线程恢复运行。

所以这里只提及了上述的两种方法。

volatile变量

我们可以自己实现的线程中设置了volatile的变量,然后在线程内部判断volatile是否满足运行的条件,满足就继续运行,不满足就退出线程。我们可以在调用线程的地方设置这个volatile变量,通过对volatile的设置达到停止线程的目的。

这里为什么使用volatile变量呢,因为volatile变量会保证多线程之间的可见性,变量的值一经修改所有的线程都能看到这个改变,根据这一性质才能停止线程的运行。

一个简单的例子:

public class ThreadInterrupt extends Thread{
   
    private volatile boolean exit = false;

    @Override
    public void run() {
   
        while (!exit) {
   
            System.out.println("Running!");
        }
    }


    public static void main(String[] args) throws Exception {
   
        ThreadInterrupt thread = new ThreadInterrupt();
        thread.start();
        sleep(10);
        thread.exit = true;
        thread.join();
        System.out.println("线程已退出!");
    }
}

但是,使用volatile变量停止线程还是不够全面,某些情况下索然可用,但是某些情况下可能会有严重的问题。

Java并发编程实战指出了其缺陷:如果我们遇到了线程长时间阻塞(例如生产者消费者中就存在这样的情况),就没办法及时唤醒它,或者永远都无法唤醒该线程。此时我们就可以使用interrupt了,interrupt在设计之初就把wait等长阻塞作为一种特殊情况考虑在内,所以可以在线程内部有sleep或者wait方法时使用interrupt方法停止线程。

interrupt()方法

我们首先看看线程中断的几个方法:

  1. java.lang.Thread#interrupt():中断目标线程,给目标线程发出一个中断信号,线程被打上中断标记
  2. java.lang.Thread#isInterrupted():判断目标线程是否被中断,不会清除中断标记
  3. java.lang.Thread#interrupted():判断目标线程是否被中断,会清除中断标记

image-20210511125815169

从上图源码可以发现,interrupted()方法和isInterrupted()方法都调用了本地isInterrupted()方法,该方法根据传入的参数决定是否清除中断状态,如果ClearInterrupted为true的话就要清除线程的中断标志,如果为false则不会清除。

使用interrupt暂停线程又有两种场景,第一种场景是线程的run方法中没有sleep和wait等会响应中断的方法,第二种场景就是有sleep和wait方法。我们首先来看看run方法中不包含sleep和wait方法的场景。

run方法不包含sleep和wait等响应中断的方法

我们首先看一个错误的示范。

首先我们看看打印Integ.MAX_VALUE/10以内的1000000倍数:

public static void main(String[] args) throws Exception {
   
    int i = 0;
    while (i < Integer.MAX_VALUE / 10) {
   
        if (i 
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值