【Android面试-Java-V15】线程中断

107 阅读2分钟

线程中断

中断代表线程状态,每个线程都关联了一个中断状态,是一个 true 或 false 的 boolean 值,初始值为 false。

Thread类中的有个三个关于中断的方法

public void interrupt(){}

中断目标线程,线程中断状态true。

public void interrupt() {                                             
    if (this != Thread.currentThread())                               
        checkAccess();                                              
                              
    synchronized (blockerLock) {                                      
        Interruptible b = blocker;                                    
        if (b != null) {                                              
            interrupt0();           // Just to set the interrupt flag 
            b.interrupt(this);                                        
            return;                                                   
        }                                                             
    }                                                                 
    interrupt0();                                                     
}                   
​
  • 当线程被Object中定义的 wait()、wait(long)或wait(long, int)以及Thread中的jion()、join(long)、join(long, int)、sleep(long)或sleep(long, int)进入阻塞状态,调用interrupt()时线程的中断标记会被清除(设置为false),同时抛出一个InterruptedException异常。
  • 当线程处于非阻塞的运行状态时,调用interrupt()方法不会响应。一般通过Thread.isInterrupted()判断状态。
public static boolean interrupted() {}
public static boolean interrupted() {                                      
    return currentThread().isInterrupted(true);                            
} 

用于判断当前线程的中断状态,调用时会清除当前线程的中断状态(置为flase),连续调用两次返回false。

public boolean isInterrupted() {}
public boolean isInterrupted() {                                           
    return isInterrupted(false);                                           
} 
​

判断目标线程是否被中断,不会清除中断标记。


中断状态被清除的特殊情况

1.当一个线程处于被阻塞状态,使用public void interrupt(){}方式中断该线程,将会抛出一个InterruptedException的异常,同时中断状态将会被清除(从true变成false)
 public static void main(String[] args) {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                // while在try中,通过异常中断就可以退出run循环
                try {
                    while (true) {
                        // 当前线程处于阻塞状态,异常必须捕捉处理,无法往外抛出
                        Thread.sleep(2000);
                    }
                } catch (InterruptedException e) {
                    System.out.println("Interruted When Sleep");
                    boolean interrupt = this.isInterrupted();
                    // 中断状态被复位
                    System.out.println("interrupt:" + interrupt);
                }
            }
        };
        t1.start();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 中断处于阻塞状态的线程
        t1.interrupt();
    }
​

输出

Interruted When Sleep
interrupt:false

要注意while中判断的写法,容易引起死循环。

while(!this.isInterrupted())

中断与synchronized

线程的中断操作对于正在等待获取的锁对象的synchronized方法或者代码块并不起作用

public class ThreadInterruptTest {
​
    public static void main(String[] args) {
        try {
            Object object = new Object();
​
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        synchronized (object) {
                            Thread.sleep(5000);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
​
            Thread.sleep(2000);
​
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (object){
                        System.out.println("get lock");
                    }
                }
            });
​
            thread.start();
​
            Thread.sleep(1000);
​
            thread.interrupt();
​
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
​

5秒之后打印:

get lock

如何退出线程?

1.使用voliate变量

public class Interrupt {
​
​
    private volatile static boolean flag = false;
​
    public static void main(String[] args) throws InterruptedException {
​
​
        Thread thread = new Thread(() -> {
            while (!flag) {
                System.out.println("thread Running");
            }
            System.out.println("thread break");
​
        });
        thread.start();
        Thread.sleep(2000);
        flag = true;
    }
​
​
}