什么是中断?
1、比如现在下载一个几百兆的视频,这时候要去下载另一个文件,暂停这个视频,那就是中断该线程,但是这种状态是阻塞的
2、那么想要改变阻塞的状态,通常在线程sleep、wait、join的情况下可以使用中断
3、由于中断可以捕获,通过这种方式可以终结线程
4、中断不是线程结束,只是发送一个 中断信号而已,线程退出还要手动加上自己的线程结束操作
中断分为两种,一种可中断的阻塞,一种不可中断的阻塞
将线程置为中断状态
需要注意的点:线程中断只是改变线程中断状态位,不会停止线程。
需要用户线程自己监视线程的状态位并作出相应的处理。支持线程中断的方法(线程中断后会抛出interruptedException异常)
就是在监视线程的中断状态,一旦线程被置为中断状态,就会抛出中断异常
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
// Just to set the interrupt flag ,native方法
interrupt0();
b.interrupt(this);
return;
}
}
interrupt0();
}
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
private native boolean isInterrupted(boolean ClearInterrupted);
interrupted方法作用于当前线程currentThread,isInterrupted是调用该方法的线程对象所对应的线程(A可以调用B线程对象的isInterrupted方法)
public boolean isInterrupted() {
return isInterrupted(false);
}
该方法都调用了底层的native isInterrupted方法,只是方法一个为true,一个为false。
可以看到 ClearInterrupted 这个参数,代表是清除中断状态
如果参数为true,返回线程状态位,清楚中断状态。参数为false,直接返回
Thread类的sleep(),wait()等方法,在接收到interrupt()方法中断时,会抛出异常,同时会将中断标志置为false,如果确实需要中断该线程,则应该在捕捉到异常后,继续调用interrupt()方法进行中断。
为什么不在异常时直接中断线程呢?主要是为了防止线程的资源没有得到释放而中断了线程
比如以下
import java.util.concurrent.TimeUnit;
public class Demo {
public static void main(String[] args) {
Object obj = new Object();
Thread thread = new Thread(new Test(obj), "thread-1");
thread.start();
try {
TimeUnit.MILLISECONDS.sleep(1);
//2、抛出java.lang.InterruptedException
thread.interrupt();
TimeUnit.MILLISECONDS.sleep(1);
thread.interrupt();
} catch (Exception e) {
e.printStackTrace();
}
}
static class Test implements Runnable {
Object obj;
public Test(Object obj) {
this.obj = obj;
}
@Override
public void run() {
synchronized(obj) {
try {
//1、首先输出该句(thread-1 before wait)
System.out.println(Thread.currentThread().getName() + " before wait");
obj.wait();
//3、输出Thread[thread-1,5,main],wait interrupte :false
System.out.println(Thread.currentThread().getName() + " after wait");
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println(Thread.currentThread() + ",wait interrupted :" + Thread.currentThread().isInterrupted());
}
}
try {
//4、输出thread-1 before sleep
System.out.println(Thread.currentThread().getName() + " before sleep");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " after sleep");
} catch (InterruptedException e) {
e.printStackTrace();
//5、输出Thread[thread-1,5,main],sleep interrupte :false
System.out.println(Thread.currentThread() + ",sleep interrupted :" + Thread.currentThread().isInterrupted());
}
//6、输出end
System.out.println("end");
}
}
}
中断会使这些方法从阻塞状态中提前返回,并且在抛出异常是清除了中断状态
那么想要重新设置中断状态可以在catch中重新设置中断。
1、interrupt()是用来设置中断状态的,isInterrupted()只是简单的查询中断状态,不会对状态进行修改
2、中断是一种协作机制。当一个线程中断另一个线程时,被中断的线程不一定要立即停止正在做的事情。相反,中断是礼貌地请求另一个线程在它愿意并且方便的时候停止它正在做的事情。
有些方法,例如 Thread.sleep(),很认真地对待这样的请求,但每个方法不是一定要对中断作出响应。对于中断请求,不阻塞但是仍然要花较长时间执行的方法可以轮询中断状态,并在被中断的时候提前返回。 您可以随意忽略中断请求,但是这样做的话会影响响应。
3、当另一个线程通过调用 Thread.interrupt() 中断一个线程时,会出现以下两种情况之一
1. 那个线程在执行一个低级可中断阻塞方法,例如 Thread.sleep()、 Thread.join() 或 Object.wait(),那么它将取消阻塞并抛出 InterruptedException. 因为这些阻塞方法,由于无法预测什么时间会结束,因此需要一种中断机制来进行通知该线程的调用者,让调用者明白该线程已经发生中断并且提前返回.
注意:这些方法会在异常抛出的时候会清除当前线程的中断状态拿wait()
方法的源码看一下就可以了