JAVA并发编程——线程中断机制与interrupt()

苏凌峰

1.线程中断是什么

2.中断的相关API方法

3.通过一个volatile变量实现线程中断

4.通过Thread类自带的中断api方法实现

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

6.静态方法Thread.interrupted()介绍

7.总结

1.线程中断是什么
我们都知道,JAVA启动一个线程很容易,而且我们都是通过线程结束之后才停止,但是我们会不会有这样一种情况,那就是线程在运行到一半的时候,我们人为地把这个运行到一半的线程给停止,这就是今天我们要说的,线程中断机制。

点开Thread.java的源码,我们发现是有stop,suspend(挂起),resume(恢复) 等方法,但是这些方法都已经被弃用了,所以不能使用。
image.png

在现在的多线程编程中,一个线程不应该由其它线程强制中断或者停止,而是应该由线程自己停止,所以上面几个方法被弃用了。

在JAVA中没有办法立即停止一个线程,然而停止线程显得尤为重要,比如取消一个非常耗时的操作,所以JAVA提供了一种停止线程的机制————中断

中断只是一种协作机制,JAVA没有给中断增加任何的语法,中断的过程完全需要程序员自己实现。

若要中断一个线程,你需要手动调用该线程的interrupt方法,该方法也仅仅是将线程对象的中断标识设置成true;

接着你需要自己写代码不断检测当前线程的标示位,如果为true,标识别的线程要求这条线程中断,此时究竟做什么需要你自己写代码实现

每个线程对象中都有一个标识,用于标识线程是否被中断:
该标识true表示中断,false表示未中断;

通过调用线程对象的interrupt方法将该线程的标示位设置为true,可以在别的线程中调用,也可以在自己的线程中调用。

2.中断的相关API方法

//实例方法interrupt()仅仅只是设置线程的中断标志位为true,不会停止线程
public void interrupt();

//这个方法做了两件事
//1.返回当前线程的中断状态
//2.将当前线程的中断状态设置为true
public static boolean interrupted();

//判断当前线程是否被中断
public boolean isInterrupted()

3.通过一个volatile变量实现线程中断

public class InterruptDemo {
    //这是一个中断的标志位
    private static volatile boolean isStop = false;

    public static void main(String[] args) {
        //启动一个线程,一直进行循环,如果中断的标志位被其它线程改成了true,则停止线程的执行
        new Thread(() -> {
            while (true) {
                if (isStop) {
                    System.out.println(Thread.currentThread().getName() + "线程------isStop = true,自己退出了");
                    break;
                }
                System.out.println("-------hello interrupt");
            }
        }, "t1").start();

        //暂停几秒钟线程
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        isStop = true;
    }

}

4.通过Thread类自带的中断api方法实现

public class InterruptDemo2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while(true){
                System.out.println("线程正在运行");
                if(Thread.currentThread().isInterrupted()){
                    System.out.println("线程被打断 isInterrupted: " + Thread.currentThread().isInterrupted());
                    break;
                }
            }
        }, "t1");
        t1.start();

        //活动状态,t1线程还在执行中
        try {
            TimeUnit.MILLISECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //打断线程
        t1.interrupt();
        //让线程跳出循环程序
        try {
            TimeUnit.MILLISECONDS.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

5.当前线程的中断标识为true,是不是就立刻停止?
从上面那两个案例中可以看出,中断只是一种协同机制,修改中断标识位仅此而已,而不是理科stop打断。

6.静态方法Thread.interrupted()介绍

这个方法,主要是有两个作用:
1)判断当前线程是否被中断,并返回这个标志位(就是返回当前线程的中断状态)
2)清除当前线程的中断状态

    public static void main(String[] args) throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "---" + Thread.interrupted());
        System.out.println(Thread.currentThread().getName() + "---" + Thread.interrupted());
        System.out.println("111111");
        Thread.currentThread().interrupt();
        System.out.println("222222");
        System.out.println(Thread.currentThread().getName() + "---" + Thread.interrupted());
        System.out.println(Thread.currentThread().getName() + "---" + Thread.interrupted());
    }

返回结果为:
image.png

可以看出,

还没有调用interrupt()方法的时候:
调用interrupted()返回的当前线程中断状态都是false(未被中断)。

调用了interrupt()方法之后:
第一次调用interrupted(),返回当前的中断状态为(true),并且清除了当前线程的中断状态,从true改为false。
第二次调用interrupted(),返回当前的中断状态为(false),因为当前线程的中断状态为false,所以状态不改变。

7.总结

1)中断只是一种协同机制,修改中断标识位仅此而已,不是立刻stop打断
2)手动调用该线程的interrupt方法,该方法也仅仅是将线程对象的中断标识设置成true
3)需要自己写代码不断检测当前线程的标示位,如果为true,标识别的线程要求这条线程中断,此时究竟做什么需要你自己写代码实现。
4)连续调用两次interrupted(),返回的结果可能会不相同

阅读 497

你的迷惑在于想得太多而书读的太少。

7 声望
14 粉丝
0 条评论

你的迷惑在于想得太多而书读的太少。

7 声望
14 粉丝
文章目录
宣传栏