线程的中断协商机制interrupt()、isInterrupted()、interrupted()

发布于:2023-01-05 ⋅ 阅读:(213) ⋅ 点赞:(0)

什么是中断

一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止。

所以,Thread.stop, Thread.suspend, Thread.resume 都已经被废弃了。

在Java中没有办法立即停止一条线程,然而停止线程却显得尤为重要,如取消一个耗时操作。

因此,Java提供了一种用于停止线程的协商机制——中断

中断只是一种协作协商机制,Java没有给中断增加任何语法,中断的过程完全需要程序员自己实现。若要中断一个线程,你需要手动调用该线程的interrupt方法,该方法也仅仅是将线程对象的中断标识设成true;接着你需要自己写代码不断地检测当前线程的标识位,如果为true,表示别的线程要求这条线程中断

中断相关API三大方法

public void interrupt() 实例方法,实例方法interrupt()仅仅是设置线程的中断状态为true,发起一个协商而不会立刻停止线程
public static boolean interrupted()

静态方法,Thread.interrupted();判断线程是否被中断,并清除当前中断状态这个方法做了两件事:

1 返回当前线程的中断状态

2 将当前线程的中断状态设为false(这个方法有点不好理解,因为连续调用两次的结果可能不一样。)

public boolean isInterrupted() 实例方法,判断当前线程是否被中断(通过检查中断标志位)

  interrupt()和isInterrupted()

当对一个线程,调用 interrupt() 时:

  • 如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,仅此而已。被设置中断标志的线程将继续正常运行,不受影响。所以, interrupt() 并不能真正的中断线程,需要被调用的线程自己进行配合才行。
  • 如果线程阻塞的调用sleep, wait, join 等方法,在别的线程中调用当前线程对象的interrupt方法,那么线程中断状态将被清除,重置为false,并抛出一个InterruptedException异常。会导致程序无限循环。
  • 所以需要在catch中重新调用intrrupt()方法,再次将中断状态设置为true。
public class InterruptDemo {
    public static void main(String[] args) {

        Thread t1 = new Thread(() -> {
            while(true){

                if (Thread.currentThread().isInterrupted()){
              System.out.println(Thread.currentThread().getName()+"中断标志位:"
                        +Thread.currentThread().isInterrupted()+"程序停止");
                break;
                }

                try {
                    Thread.sleep(200);//中断状态清除
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
            System.out.println("hello Interrupt");
            }
        },"t1");
        t1.start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()-> t1.interrupt(),"t2").start();
    }
}


当前线程的中断标识为true,是不是线程就立刻停止?

如果线程处于正常活动状态,那么会将该线程的中断标志设置为 true,仅此而已。

被设置中断标志的线程将继续正常运行,不受影响。所以, interrupt() 并不能真正的中断线程,需要被调用的线程自己进行配合才行。

总结:

  • 中断只是一种协同机制,修改中断标识位仅此而已,而不是立刻stop打断

 静态方法Thread.interrupted()

静态方法,Thread.interrupted();判断线程是否被中断,并清除当前中断状态这个方法做了两件事

1 返回当前线程的中断状态

2 将当前线程的中断状态设为false

public class InterruptDemo {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName()+"---"+Thread.interrupted());
        System.out.println(Thread.currentThread().getName()+"---"+Thread.interrupted());
        System.out.println("111");
        Thread.currentThread().interrupt();
        System.out.println("222");
        System.out.println(Thread.currentThread().getName()+"---"+Thread.interrupted());
        System.out.println(Thread.currentThread().getName()+"---"+Thread.interrupted());


    }

main---false
main---false
111
222
main---true// 将当前线程中断状态返回并设置为false
main---false

interrupted()对比isInterrupted()

  1. 一个是静态方法,一个是实例方法
  2. 底层都调用了native方法isInterrupted。

静态方法interrupted将会清除中断状态(传入的参数ClearInterrupted为true),

实例方法isInterrupted则不会(传入的参数Clearlnterrupted为false)。

 方法的注释也清晰的表达了“中断状态将会根据传入的Clearlnterrupted参数值确定是否重置”。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到