【Java 进阶知识】线程的中断——interrupt()

既然我们使得一个线程开始运行,那如果没有异常情况,线程将会一直运行直到代码执行完毕。当然,如果我们在线程运行中途想去终止此线程,也是有方法的。
通常我们使用interrup方法接下来,为大家引入这个方法的使用:

1.isInterrupted()、interrupted()方法的使用

  • 对于每一个线程,都会有一个Boolean类型中断标志位,该标志位默认false,表示没有被中断我们可以调用线程的isInterrupted()方法来查看当前的中断标志位的状态,该标志位不影响线程的状态。
    在这里插入图片描述
  • 另外,还有一个类似的方法interrupted()也是可以检查当前线程是否中断,但在调用该方法后,如果标志位为true,该方法会将标志位重置为false。
    在这里插入图片描述
    现在,我们通过代码来演示二者的差别:
public class InterruptThread {
    public static void main(String[] args) {
    
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
                   boolean a = Thread.interrupted();
                   boolean b = Thread.currentThread().isInterrupted();
                    //表示创建后初始标志位是false,表示没有被中断
                    System.out.println(b);
                }
            }
        });
        thread.start();
    }
}

在这个代码中,主要工作就是创建了一个线程,让这个线程循环十次打印出标志位的状态。
当我们没有对线程进行中断时,a、b均会分别默认打印出10个false,这就证明在没中断线程时,默认标志位为false
接下来,对线程进行中断操作:

public class InterruptThread {
    public static void main(String[] args) {
    
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 10; i++) {
               	   boolean a = Thread.interrupted();
                   boolean b = Thread.currentThread().isInterrupted();
                    //表示创建后初始标志位是false,表示没有被中断
                    System.out.println(b);
                }
            }
        });
        thread.start();
        thread.interrupt();
    }
}

此时,我们加入了堆线程的中断操作后,再次分别调用interrupted()和isInterrupted()方法。此时,前者将会打印出1个true和9个false,而后者会打印出10个true
这就证实了我们上面提到过的,使用interrupted()这个静态方法,会返回当前的标志位并且将标志位重置为true,而使用isInterrupted()这个实例方法就仅仅返沪这个标志位的状态而不会更改其值。

2.interrupt()方法

  • 使用interrupt可以中断一个线程
  • 如果线程调用了 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式通知,清除
    中断标志

同样,代码演示:

public class InterruptThread {
    public static void main(String[] args) throws InterruptedException {

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().isInterrupted());
                }
                try {
                //调用sleep()/wait()/join()方法时,线程进入阻塞状态,
                    // 此时也可以进行中断,中断后抛出异常,抛出后重置标志位为false
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().isInterrupted());
                }
            }
        });
        thread.start();
        thread.interrupt();
   }
}

上述代码中,我们创建了一个线程,在这个线程中循环输出五次标志位的状态。在抛出异常后,再次输出五次标志位状态。
运行代码得到如下结果:
在这里插入图片描述
这意味着,在执行了interrupt方法后,确实将线程的中断标志位置为true,但由于线程此时调用了sleep方法使得线程超时等待状态,这时就抛出一个异常。在抛出异常后,标志位就被重置为false,所以再次打印标志位就变为false。
所以,我们使用interrupt方法的优势是可以中断阻塞线程

3.总结

方法 说明
public void interrupt() 中断对象关联,如果线程正在阻塞,则以异常形式通知,否则设置标志位
public static boolean interrupted() 判断当前线程的中断标志位是否设置,调用后清除标志位
public boolean isInterrupted() 判断当前线程的中断标志位是否设置,调用后不清除标志位
发布了62 篇原创文章 · 获赞 28 · 访问量 6062

猜你喜欢

转载自blog.csdn.net/Moo_Lavender/article/details/103109341