前言:之前在看Thread源码的时候,看到interrupt相关的方法,回想之前一直经常遇到的InterruptedException,于是决定好好了解一下interrupt机制,这就是我们经常提起的线程中断机制,以前遇到中断异常时,经常性地忽略该异常,其实这是一种很不负责的做法,在深入学习了中断机制后,明白了中断也是一种很重要的处理机制
那么什么是中断机制?
1.中断是一种协作机制,既然是协作,那么就是商量着来处理事情,当一个线程A去尝试中断线程B时,线程B不一定会立刻停止当前正在处理的事情,而是在方便的时候停止
2.中断机制通常对于阻塞方法是有效的,也就是当线程执行阻塞方法并进入阻塞状态时,这时就是上面提到的方便的时候,常见的可中断的阻塞方法:Thread.sleep()、Object.wait()、Queue.take()
3.不可中断的阻塞方法,例如:IO/NIO的read/write操作,sychronized获取内部锁
注:ReentrantLock 支持可中断的获取模式
中断方法
中断方法有哪些:
1.void interrupt():中断线程,将线程的中断状态置为true
2.boolean isInterrupted():线程中断状态是否为true
3.boolean interrupted():线程中断状态是否为true并将中断状态重置为false,所以多次调用该方法,后面会返回false
注:中断状态是与线程关联的一个属性,初始为false,调用本地方法才能获取
三种方法的具体使用如下:
public static void interrupt()
{
//interrupt方法是设置当前线程的中断状态为true,具体线程的中断处理在方便的时候执行
Thread.currentThread().interrupt();
try
{
//线程进入阻塞状态,这时就是方便处理中断的时候
TimeUnit.SECONDS.sleep(10);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public static void isInterrupted()
{
Thread.currentThread().interrupt();
System.out.println(String.format("首次调用interrupt方法,返回:%s", Thread.currentThread().isInterrupted()));
System.out.println(String.format("再次调用interrupt方法,返回:%s", Thread.currentThread().isInterrupted()));
}
public static void interrupted()
{
Thread.currentThread().interrupt();
System.out.println(String.format("首次调用interrupted方法,返回:%s", Thread.interrupted()));
System.out.println(String.format("再次调用interrupted方法,返回:%s", Thread.interrupted()));
}
public static void main(String[] args)
{
interrupt();
isInterrupted();
interrupted();
}
日志打印如下:
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:360)
at com.interrupt.InterruptSevice.interrupt(InterruptSevice.java:23)
at com.interrupt.InterruptSevice.main(InterruptSevice.java:48)
首次调用interrupt方法,返回:true
再次调用interrupt方法,返回:true
首次调用interrupted方法,返回:true
再次调用interrupted方法,返回:false
中断方法具体有哪些应用?
1.通过轮询中断状态,在非阻塞方法中实现任务取消
验证如下:
public static void fastResponse()
{
while(true)
{
if(Thread.currentThread().isInterrupted())
{
System.out.println("当前中断状态为true,跳出循环!");
break;
}
}
}
public static void main(String[] args)
{
//中断线程
Thread.currentThread().interrupt();
fastResponse();
}
日志打印:
中断异常
中断异常对中断状态有什么影响?
1.程序抛出中断异常后,这时底层就会将中断状态置为false
验证如下:
public static void interrupt()
{
//interrupt方法是设置当前线程的中断状态为true,具体线程的中断处理在方便的时候执行
Thread.currentThread().interrupt();
try
{
//线程进入阻塞状态,这时就是方便处理中断的时候
TimeUnit.SECONDS.sleep(10);
}
catch (InterruptedException e)
{
System.out.println(String.format("调用interrupt方法,返回:%s", Thread.currentThread().isInterrupted()));
e.printStackTrace();
}
}
public static void main(String[] args)
{
interrupt();
}
日志打印:
调用interrupt方法,返回:false
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:360)
at com.interrupt.InterruptSevice.interrupt(InterruptSevice.java:23)
at com.interrupt.InterruptSevice.main(InterruptSevice.java:88)
如何处理中断异常(InterruptedException)?
1.捕获到中断异常后如果不需要做处理,则抛给上层处理
2.线程在抛出中断异常后,如果使用了try catch,那么需要在catch中调用Thread.interrupt(),将中断状态置为true,方便上层方法栈能够正常做中断操作
将中断异常吞掉会有什么后果?
1.一个中断请求,可能有多个接收者,如果其中一个接收者吞掉了异常,则其他接收者无法正常中断
验证如下:
public static void swallowInterrupt()
{
Thread.currentThread().interrupt();
try
{
System.out.println("休眠1秒!");
TimeUnit.SECONDS.sleep(1);
}
catch (InterruptedException e)
{
System.out.println("线程中断!");
System.out.println("吞掉异常!");
}
try
{
System.out.println("休眠2秒!");
TimeUnit.SECONDS.sleep(2);
}
catch (InterruptedException e)
{
System.out.println("线程再次中断!");
}
}
public static void main(String[] args)
{
swallowInterrupt();
}
日志打印: