一直对Thread.interrupt()接口不是太清楚,之前以为是直接中止指定线程的接口,后来仔细了解,发现并不是,而是只是在jvm中设置了指定线程的状态值为“中止”,但是并不主动去中止线程,如何处理的权限交给了写线程运行代码的用户。如下面例子
public class ThreadApiTest implementsRunnable {
Threadtest = new Thread(new ThreadApiTest());
test.start();
try{
Thread.sleep(10000);
}catch (InterruptedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
test.interrupt();
System.out.println(Thread.currentThread().getName()+"isend!");
}
publicvoid run() {
//TODO Auto-generated method stub
while(true){
System.out.println(Thread.currentThread().getName()+"isalive!");
try{
Thread.sleep(1000);
}catch (InterruptedException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
运行结果:
Thread-0is alive!
Thread-0is alive!
Thread-0is alive!
Thread-0is alive!
mainis end!
java.lang.InterruptedException: sleepinterrupted
Thread-0is alive!
atjava.lang.Thread.sleep(Native Method)
atcom.tisson.zrftest.ThreadApiTest.run(ThreadApiTest.java:44)
atjava.lang.Thread.run(Unknown Source)
Thread-0is alive!
Thread-0is alive!
--在主线程调用test.interrupt();并且主线程运行完毕后,test线程并没有如意料中那样终止,而是抛出一个InterruptedException:后继续运行,所以可以确定,interrupt()没有主动终止线程的能力,而是只是设置了改线程的状态为中止。但是当线程在执行object.wait(),Thread.sleep(),Thread.join()属于诸塞状态时时会抛出InterruptedException。除此之外,interrupt()并没有做更多的工作。另外相关的api接口有Thread.currentThread().isInterrupted()和Thread.interrupted(),如果在run的catch 语句块中增加两行代码:
System.out.println(Thread.currentThread().isInterrupted());
System.out.println(Thread.interrupted());
--会发现输出结果是false,false,因为当线程抛出InterruptedException异常后也把线程的中止状态也清理了。另外值得注意的是isInterrupted()是Thread的普通成员方法,interrupted()是Thread的静态成员方法。另外前者只会返回状态而不会清理,后者返回状态的同时进行了清理。源码分析,让我们看看,为什么interrupt()并没有终止线程的能力。
private volatile Interruptible blocker;
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
--可以明显看到blocker并没有在Thread类中进行初始化,那么blocker应该还是为null,所以当我们调用interrupt()时并没有满足if (b!= null)的条件,所以并没有执行b.interrupt(this);只是执行了interrupt0();而前者是真正能中断线程的,后者只是设置中止状态(Just to set the interrupt flag),找不到b.interrupt(this)里面的源码,姑且认为它是能通过抛出异常的方式打断线程。也就是说InterruptedException异常并非sleep抛出的,而是interrupt()抛出的,也就是在线程还在阻塞时interrupt()抛出异常打断阻塞,线程运行阻塞后的命令时捕捉到该异常。