线程中断之-interrupt()、isInterrupted()、interrupted()

线程中断是线程通讯的一种手段,设置线程的中断标识并不意味着该线程会立即挂起,相反,如果该线程对自己的中断标识的变化不采取任何手段,则该中断标识将没有任何意义,程序将继续向下运行。

主要涉及到三个主要API。

1. interrupt()

1.1 测试中断之后线程是否会继续执行

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

        Thread thread = new Thread(() -> {
            for (; ; ) {
                System.out.println(Thread.currentThread().getName() + " is saying hello");
            }
        });

        //启动thread线程
        thread.start();

        //main线程首先等待1S,目的是让thread线程首先启动
        Thread.sleep(1000);

        //设置中断标识
        thread.interrupt();
    }

运行结果:程序会不断进行打印,并不会终止

1.2 线程中断标志的正确使用方法

通常在两个场景下线程会被设置中断标志

  1. 其他线程认为该线程应该终止当前的操作
public static void main(String[] args) throws InterruptedException {

        Thread thread = new Thread(() -> {
            //如果当前线程没有被设置中断标志,则该线程继续运行
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println(Thread.currentThread().getName() + " is go on working");
            }
        });

        //启动thread线程
        thread.start();

        //main线程首先等待1S,目的是让thread线程首先启动
        Thread.sleep(1000);

        //设置中断标识
        thread.interrupt();
    }

运行结果:1S之后程序会停止

该程序和上一段程序的唯一区别就在于for循环变成了while循环,并且在while循环中不断地检查当前线程是否被设置中断标志,这也是isInterrupted()的标准使用方法。

  1. 打断目标线程的阻塞状态(wait,join,sleep导致),强制抛出异常并返回
 public static void main() throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                System.out.println("线程即将进入睡眠...");
                Thread.sleep(1000000);
                System.out.println("线程被唤醒...");
            } catch (InterruptedException e) {
                System.out.println("线程睡眠过程中被打断");
                //使该线程继续向下运行
            }
            System.out.println("其他业务被执行");
        });

        //启动thread线程
        thread.start();

        //main线程首先等待1S,目的是让thread线程首先启动
        Thread.sleep(1000);

        //打断子线程sleep状态,抛出异常强行退出
        thread.interrupt();

    }

运行结果如下:
线程中断之-interrupt()、isInterrupted()、interrupted()_第1张图片

2. boolean isInterrupted()

检测当前线程是否被设置中断标志,是则返回true,否则返回false
相比于接下来介绍的interrupted(),该方法更加常用
在这里插入图片描述
查看该函数源码发现,其调用的子函数带有一个boolean类型的参数,表示是否清除中断标记。
因此isInterrupted()函数仅仅返回中断标志,不会清除中断标志。

3. interrupted()

查看源码
在这里插入图片描述
该函数和isInterrupted()有3点不同

  1. 该方法为static方法,可以直接利用Thread调用
  2. 该方法返回的调用该方法的当前线程的终端状态,而不是被调用线程的中断状态
  3. 该方法的会清除线程的中断标记

下面通过一个例子更好的理解isInterrupted()和interrupted()之间的区别(例子摘取自《并发编程之美》)

public static void compare() throws InterruptedException {
        Thread thread = new Thread(() -> {
            for (; ; ) {

            }
        });

        //启动线程
        thread.start();

        //设置中断标志
        thread.interrupt();

        //1.获取中断标志
        System.out.println("isInterrupted:" + thread.isInterrupted());

        //2.获取中断标志并重置
        System.out.println("interrupted:" + thread.interrupted());

        //3.获取中断标志并重置
        System.out.println("interrupted:" + Thread.interrupted());

        //4.获取中断标志
        System.out.println("isInterrupted:" + thread.isInterrupted());
        
        thread.join();

    }

大家不妨先自己理解一下给出自己的答案
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

输出结果
在这里插入图片描述

第一个打印结果是true应该是很容易理解的,因为thread线程被主线程设置了中断标记,因此isinterrupted()为true

第二个打印结果为false可能很多人不理解了,这是因为上文说过的interrupted()这个函数获取的是当前线程的终端状态,因为当前线程是主线程,所以和thread无关(虽然实在thread上调用的该函数)

第三个打印结果同理,由此可见,这里thread.interrupted()和Thread.interrupted()是等价的

第四个打印结果为true,因为isInterrupted()获取的还是thread的中断状态

你可能感兴趣的:(并发编程,多线程,线程中断,多线程学习笔记)