作用:给线程打上中断标记
我们不能直接把一个线程搞挂掉, 但有时候又有必要让一个线程死掉, 或者让它结束某种等待的状态 该怎么办呢?一个比较优雅而安全的做法是:使用等待/通知机制或者给那个线程一个中断信号, 让它自己决定该怎么办。
相关方法(后面两个方法都是检查是否被打上了中断标记,第二个方法是Thread的类方法,第三个方法是对象方法)
两种获取中断状态方法的区别
- Thread.currentThread().interrupted();该方法返回为true的时候,会将中断状态重置为false
- Thread.isInterrupted();该方法不会重置中断状态,且为静态方法
Interrupted和isInterrupted的应用场景如下:
当在线程实例对象外部检查线程是否被打断时使用isInterrupted方法:
当传入的Runnable的实现类,并且在实现类中检查线程是否被中断时,使用Thread类的Interrupted方法:
Interrupt方法的官方文档
- 调用thread.interrupt(),会告知被调用线程中断状态为true.
- 对于非阻塞中的线程, 只是中断状态改变为true
- 对于阻塞状态中的线程, 比如等待在这些函数上的线程, Thread.sleep(), Object.wait(), Thread.join(), 这个线程收到中断信号后, 会抛出InterruptedException,同时中断状态改变为false,因为抛出异常意味着该线程已被打断。
- 在使用synchronized关键字获取锁的过程中不响应中断请求,即线程interrupt后仍需要争抢锁才能响应中断请求。如果这对程序是一个问题,可以使用显式锁,即java中Lock接口,它支持以响应中断的方式获取锁。
以sleep方式进行打断
public class ThreadInterrupt {
public static void main(String[] args) throws InterruptedException{
Thread t=new Thread(){
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
System.out.println("收到打断信号");
e.printStackTrace();
}
}
}
};
t.start();
Thread.sleep(100);
System.out.println(t.isInterrupted());
t.interrupt();
System.out.println(t.isInterrupted());
}
运行结果:
false
true
收到打断信号
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.learn.thread.chapter6.ThreadInterrupt$1.run(ThreadInterrupt.java:10)
以join方法进行打断:
public static void main(String[] args) {
Thread main=Thread.currentThread();
Thread t2=new Thread(){
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
main.interrupt();//main线程被打上了中断标记
System.out.println("interrupt");
}
};
t2.start();
try {
t2.join();//join方法会将main线程阻塞,此时,如果main线程收到了中断信号(执行main.interrupt())时就会在main线程中抛出异常
//注意异常抛出的位置是在被阻塞的位置。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
运行结果:
interrupt
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Thread.join(Thread.java:1252)
at java.lang.Thread.join(Thread.java:1326)
at com.learn.thread.chapter6.ThreadInterrupt.main(ThreadInterrupt.java:30)