InterruptedException异常:
声明了抛出InterruptedException异常的方法(轻量级阻塞的方法),线程在阻塞时,其他线程(比如主线程)调用这个线程的interrupt()方法,阻塞线程会抛出InterruptedException异常并从阻塞状态中跳出。
声明了InterruptedException的方法有
public static native void sleep(long millis) throws InterruptedException{//...}
public final void wait() throws InterruptedException {//...}
public final void join() throws InterruptedException {//...}
代码举例
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
//thread线程在sleep中被中断
thread.interrupt();
//主线程sleep防止main方法结束太快
Thread.sleep(1000);
System.exit(0);
}
}
能够被中断的阻塞称为轻量级阻塞,对应的线程状态是WAITING或者TIMED_WAITING;而像 synchronized 这种不能被中断的阻塞称为重量级阻塞,对应的状态是 BLOCKED
线程的状态(Thread.States类):
NEW:Thread对象已经创建,但是还没有开始执行。
RUNNABLE:Thread对象正在Java虚拟机中运行。 BLOCKED : Thread对象正在等待锁定。
WAITING:Thread 对象正在等待另一个线程的动作。
TIME_WAITING:Thread对象正在等待另一个线程的操作,但是有时间限制。
TERMINATED:Thread对象已经完成了执行。
初始线程处于NEW状态,调用start()开始执行后,进入RUNNING或者READY状态。如果没有调用 任何的阻塞函数,线程只会在RUNNING和READY之间切换,也就是系统的时间片调度。这两种状态的 切换是操作系统完成的,除非手动调用yield()函数,放弃对CPU的占用。
一旦调用了任何阻塞函数,线程就会进入WAITING或者TIMED_WAITING状态,两者的区别 只是前者为无限期阻塞,后者则传入了一个时间参数,阻塞一个有限的时间。如果使用了synchronized 关键字或者synchronized块,则会进入BLOCKED状态。
thread.interrupted()的实际含义应该是“唤醒轻量级阻塞”,而不是字面意思“中断一个线程”。
thread.isInterrupted()与Thread.interrupted()
这两个方法都是线程用来判断是否收到过中断信号(thread.interrupt())的,前者是实例方法,后者是静态方法。前者只是读取中断状态,不修改状态;后者不仅读取中断状态,还会重置中断标志位。
//返回某个线程的中断标志位,不重置中断标志位
public boolean isInterrupted() {
return isInterrupted(false);
}
//返回当前线程的中断标志位,重置中断标志位
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
//返回线程的中断标志位,ClearInterrupted表示是否重置标志位
private native boolean isInterrupted(boolean ClearInterrupted);
代码测试
public class MyThread extends Thread {
@Override
public void run() {
boolean interrupted = isInterrupted();
System.out.println("查看中断标记:" + interrupted);
// 检查并重置中断标志。
boolean interrupted1 = Thread.interrupted();
System.out.println("重置中断状态:" + interrupted1);
//上面重置了标志位
interrupted1 = Thread.interrupted();
System.out.println("重置中断状态:" + interrupted1);
interrupted = isInterrupted();
System.out.println("查看中断标记:" + interrupted);
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.start();
myThread.interrupt();
System.out.println("main中断状态检查-1:" + myThread.isInterrupted());
//等待myThread线程执行完毕
myThread.join();
System.out.println("main中断状态检查-2:" + myThread.isInterrupted());
}
}