上一篇博客讲过线程的中断,特别提到过interrupt()这个方法,现在来详细讲述一下这个方法,以及这个方法的用途。
JDK1.0之前,有一个方法stop()方法可以强制一个线程的中断,但是现在这个方法被废弃了,但是还是有一种方法可以请求终止一个线程,它就是interrupt()方法。
当程序运行到interrupt()方法之后,线程的(interrupt status)中断状态将会被置位。它是一个布尔类型的数据,存在于每一个线程中,将它赋值扯过true。每一个线程都应该会不时的检查它的状态。如果线程被阻塞了,那么就无法检查中断状态了,这样就会产生InterruptException异常的地方,当给一个被阻塞的线程调用interrupt方法时,阻塞调用(例如wait和sleep方法)将会被这个异常终止。
所以没有一个任何语言规定一个线程调用interrupt之后就一定会被中断,中断一个线程只是引起这个线程的注意,有时侯不仅不会出现线程中断反而是让处于阻塞状态的程序继续运行。
我下面的程序能很好的解释这一点
package test6;
public class Thread1 extends Thread {
public void run(){
int a = 10;
while(a++<52){
if(a>50){
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println(a);
}
System.out.println("i have more to do");
}
}
package test6;
public class TestThread {
public static void main(String[] args) {
Thread thread = new Thread1();
thread.start();
thread.interrupt();
}
}
在测试类中将看到,程序先从1输出到50,然后抛出一个异常,最后输出51。
所以中断线程比我们想想的要复杂得多,在写一个中断sleep状态的多线程程序。
package test6;
import java.util.Date;
public class Thread2 extends Thread{
public void run(){
System.out.println("睡眠之前");
long start = System.currentTimeMillis();
try {
Thread2.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("程序运行的时间是"+(end-start));
System.out.println("睡眠之后");
}
}
package test6;
public class TestThread {
public static void main(String[] args) {
Thread thread = new Thread2();
thread.start();
thread.interrupt();//将这句话注释掉就能看到效果了
}
}
打断是运行只有1ms ,不打断1000ms。这就是效果了。
值得注意的是,当sleep方法抛出异常的时候,线程就会清除该中断状态。
JDK1.0之后,对于多线程有一些相似的方法
void interrupt():发送一个中断请求给线程,将中断状态设置为true.
static boolean interrupted():检查当前线程是不是被中断了,如果中断了就清空中断状态。
boolean isinterrupted();检查当前线程的中断状态