线程中断到底是什么

提示:更多优秀博文请移步博主的GitHub仓库:GitHub学习笔记Gitee学习笔记

我们如何让线程安全的停止呢?

1. 线程自然终止

自然执行完或抛出未处理异常。

2. stop(),resume(),suspend()方法

stop(),resume(),suspend()已不建议使用,stop()会导致线程不会正确释放资源,suspend()容易导致死锁。

  • 停止多线程: public void stop();
  • 销毁多线程: public void destory();
  • 挂起线程: public final void suspend(); 暂停执行
  • 恢复挂起的线程执行: public final void resume();

3. 线程中断

Thread类提供了interrupt方法,用于中断目标线程的执行。

3.1 interrupt方法

interrupt()方法用于中断一个线程,而Java中线程的处理是协作式的而不是抢占式的。所谓协作式的意思是:实际上调用一个线程的interrupt() 方法中断一个线程,并不是强行关闭这个线程,只是跟这个线程打个招呼,将线程的中断标志位置为true,线程是否中断,由线程本身决定。

public class UserRunnable implements Runnable {
    @Override
    public void run() {
        while (true){
            System.out.println(Thread.currentThread().getName()+"is running");
        }
    }
}
public class SafeExitTest {
    public static void main(String[] args) {
        Thread thread = new Thread(new UserRunnable());
        thread.start();
        thread.interrupt();
    }
}

我们可以看到,在UserRunnable线程中,我们并没有对中断进行任何处理,所以在SafeExitTest中调用线程的interrupt方法并不会导致线程的中断,控制台还是会继续打印。只有在目标线程中进行了正确的中断处理后才会有中断效果:

public class UserRunnable implements Runnable {
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {//判断当前线程是否被中断
            System.out.println(Thread.currentThread().getName() + "is running");
        }
    }
}

Thread类中相关方法

  • isInterrupted() :判定指定线程是否处于中断状态。
  • static interrupted() :静态方法,判定当前线程是否处于中断状态,同时将中断标志位改为false。

3.2 阻塞线程与线程中断

Java中断响应是描述当一个线程或方法A处于运行、阻塞或死锁状态时,外界(通常指其他线程、系统IO等)对A的影响能否让A线程或者方法抛出InterruptedException异常并提前返回,如果会提前返回并且抛出InterruptedException,就叫可中断响应方法或线程,如果不会抛出InterruptedException,就叫不可中断线程或方法。

Java语言中所有阻塞方法都声明抛出InterruptedException异常(例如 Thread.sleep()Thread.join()Object.wait())。也就是说,如果一个线程执行了阻塞方法,使得当前线阻塞,第三方线程执行interrupt方法中断线程,都会使得该阻塞方法抛出InterruptedException异常并退出阻塞,并且将当前线程的中断标志位设置为false

如果没有这个机制, interrupt() 则只是单纯设置线程的中断状态。那这个试图中断的线程仍在阻塞当中,那么后序的中断工作则无法进行。

3.3 阻塞线程的线程中断案例

public class UserRunnable implements Runnable {
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println(Thread.currentThread().getName() + "is running");
            try {
                Thread.sleep(10);//第7行
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class SafeExitTest {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new UserRunnable());
        thread.start();
        Thread.sleep(10);
        thread.interrupt();//第6行
    }
}

上面的代码我们仅仅是在每次循环的时候让线程sleep了10ms,但这很有可能会导致中断操作的失败(注意这里说的是很有可能)。

在这里插入图片描述

可以看到控制台不断输出"Thread-0is running",这是因为在执行SafeExitTest:6(SafeExitTest类的第6行代码)这行代码时,目标线程处于阻塞状态,此时UserRunnable:7这行代码抛出InterruptedException异常,线程退出阻塞状态,并将中断标志位设置为false。这也就是为什么虽然在while语句中对中断标志位进行了判断,而在主线程试图中断目标线程时,目标线程仍能继续循环的原因。

经过多次测试也会出现中断成功的情况:

在这里插入图片描述

出现这种情况,是因为中断操作放生在第一次循环完成和第二次循环判断开始之前。

具体细节参考

https://blog.csdn.net/meiliangdeng1990/article/details/80559012

https://www.ibm.com/developerworks/cn/java/j-jtp05236.html

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

听到微笑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值