今天是:
带着程序的旅程,每一行代码都是你前进的一步,每个错误都是你成长的机会,最终,你将抵达你的目的地。
title

interrupted

1.为什么使用中断机制

在多线程的场景中,有的线程可能迷失在怪圈无法自拔,或者执行一个超长的任务,这个时候如果别人不通知则就停不下来,别人(其他线程)也一直等待干不了活, 造成资源的浪费,这时就可以用其他线程在恰当的时机给它个中断通知,被“中断”的线程可以选择在恰当的时机选择跳出怪圈,最大化的利用CPU资源.Java没有提供一种安全直接的方法来停止某个线程,但是Java提供了中断机制。

2.Java 中断机制

如果任何线程处于睡眠或等待状态(即调用 sleep() 或 wait()),则调用该线程上的 interrupt() 方法,会中断睡眠或等待状态并抛出 InterruptedException。 如果线程未处于休眠或等待状态,则调用 interrupt() 方法会执行正常行为,并且不会中断线程,但会将中断标志设置为 true。 我们先来看看Thread类提供的线程中断方法。中断可以理解为线程的一个标识位属性,它表示一个运行中的线程是否被其他线程进行 了中断操作。中断好比其他线程对该线程打了个招呼,其他线程通过调用该线程的interrupt() 方法对其进行中断操作。 线程通过检查自身是否被中断来进行响应,线程通过方法isInterrupted()来进行判断是否 被中断,也可以调用静态方法Thread.interrupted()对当前线程的中断标识位进行复位。如果该 线程已经处于终结状态,即使该线程被中断过,在调用该线程对象的isInterrupted()时依旧会返 回false。

3.什么是打断异常

当一个线程在等待、睡眠或以其他方式被占用时被中断,就会抛出一个 InterruptedException。 换句话说,一些代码在我们的线程上调用了interrupt() 方法。 它是一个受检异常,Java 中的许多阻塞操作都可以抛出它。

3.1线程中断方法

public void interrupt() { ... }//线程调用打断方法
public boolean isInterrupted() { ... }//判断中断标志位, 线程的中断状态不受此方法的影响
public static boolean interrupted() { ... }//与interrupted类似,线程的中断状态会被清理

3.2中断标志位

中断机制是使用称为中断状态的标志来实现的。 每个线程都有一个代表其中断状态的布尔属性。 调用 Thread.interrupt() 设置此标志。 当线程通过调用静态方法 Thread.interrupted() 检查中断时,中断状态被清除。 为了响应中断请求,我们必须处理 InterruptedException。

4.中断例子

4.1 捕获打断异常

    public void testInterruptExeception(){
        Thread thread = new Thread(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().isInterrupted());
                throw new RuntimeException("Thread interrupted..."+e);
            }
        });
        thread.start();
        thread.interrupt();
    }
//outputs
false  //没有相应中断,打断状态被清理
Exception in thread "Thread-0" java.lang.RuntimeException: Thread interrupted...java.lang.InterruptedException: sleep interrupted

4.2 捕获异常后程序继续运行

    public void testInterruptExeception2(){
        Thread thread = new Thread(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("线程被打断 "+e);
            }
            System.out.println("线程继续运行。。。 ");
        });
        thread.start();
        thread.interrupt();
    }
//output
线程被打断 java.lang.InterruptedException: sleep interrupted
线程继续运行。。。 

4.3.线程没有在等待或睡眠状态,设置打断状态

    public void testInterruptExeception3(){
        Thread thread = new Thread(()->{
            for(int i=1;i<=5;i++){
                System.out.println(i);
             }
            System.out.println("thread interrupt state:"+ Thread.currentThread().isInterrupted());
        });
        thread.start();
        thread.interrupt();
    }
//output
1
2
3
4
5
thread interrupt state:true

4.4响应中断,如果不响应中断,下面的程序会一直执行

    public void testInterruptExeception4() throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {
                if (Thread.currentThread().isInterrupted()){
                    System.out.println("任务停止,结束退出!");
                    return;
                }
                else
                    System.out.println("线程运行中。。。");
            }
        });
        thread.start();
        Thread.sleep(100);
        thread.interrupt();
    }
//output
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
线程运行中。。。
.
.
.
任务停止,结束退出!

5.总结

在上面的例子中,我们讨论了如何处理中断异常,如何使线程处于中断状态,以及应该如何响应中断, 如果我们处理得当,我们可以平衡应用程序的响应性和健壮性。

分享到:

专栏

类型标签

网站访问总量