Thread的Interrupt()源代码分析(7)
今天我们来学习下interrupt(),首先先看下api上对此方法的解释,关于interrupt的方法有三个
public void interrupt()
中断这个线程。
除非当前线程中断自身,这是始终允许的,所以调用此线程的checkAccess
方法,这可能会导致抛出SecurityException
。
如果该线程阻塞的调用wait()
, wait(long)
,或wait(long, int)
的方法Object
类,或者在join()
, join(long)
, join(long, int)
, sleep(long)
,或sleep(long, int)
,这个类的方法,那么它的中断状态将被清除,并且将收到一个InterruptedException
。
如果该线程在可阻止在I / O操作InterruptibleChannel
则信道将被关闭,该线程的中断状态将被设置,并且螺纹将收到一个ClosedByInterruptException
。
如果该线程在Selector
中被阻塞,则线程的中断状态将被设置,并且它将从选择操作立即返回,可能具有非零值,就像调用了选择器的wakeup
方法一样。
如果以前的条件都不成立,则该线程的中断状态将被设置。
中断不存在的线程不需要任何效果。
异常
SecurityException
- 如果当前线程不能修改此线程
public static boolean interrupted()
测试当前线程是否中断。 该方法可以清除线程的中断状态 。 换句话说,如果这个方法被连续调用两次,那么第二个调用将返回false(除非当前线程再次中断,在第一个调用已经清除其中断状态之后,在第二个调用之前已经检查过)。
忽略线程中断,因为线程在中断时不存在将被该方法返回false所反映。
结果
true
如果当前线程已被中断; false
否则。
另请参见:
public boolean isInterrupted()
测试这个线程是否被中断。 线程的中断状态不受此方法的影响。
忽略线程中断,因为线程在中断时不存在将被该方法返回false所反映。
结果
true
如果这个线程已被中断; false
否则。
另请参见:
请看interrupt()的源代码:
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
/*判断是否为当前线程调用,如果不是则调用此线程的checkAccess方法,这可能会导致抛出SecurityException */
synchronized (blockerLock) {
/*blockerLock为当前线程创建时内部初始化的一个Object对象,被用作锁的标识对象,后面文章会讲到synchronized 同步锁*/
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
/*只是赋给线程一个状态(中断)并不是会中断该线程*/
b.interrupt(this);
return;
}
}
interrupt0();
}
接下来我们看下实现代码:
public static void main(String[] args) {
//验证interrupt
Thread t = new Thread(new Runnable() {
@Override
public void run() {
//打印当前线程是否是中断状态
while (true)
System.out.println(Thread.interrupted());
}
},"t1");
t.start();
t.interrupt();
}
控制台打印:
而此时线程还是处于中断状态。说明此方法并不会中断线程,而是赋给了一个中断的状态。
而为什么会有两个判断线程中断状态的方法(isInterrupted()和iterrupted())呢?它们两个的区别在哪里呢?
请看说明:
interrupted():测试当前线程是否中断。 该方法可以清除线程的中断状态 。
isInterrupted():测试这个线程是否被中断。 线程的中断状态不受此方法的影响。
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.interrupted());
while(true){
}
}
});
t1.start();
t1.interrupt();
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("3"+t1.interrupted());
System.out.println("4"+t1.interrupted());
再来看下isInterrupted()
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().isInterrupted());
while(true){
}
}
});
t1.start();
t1.interrupt();
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t1.isInterrupted());
System.out.println(t1.isInterrupted());
我们来看下源码给的解释:
public static boolean interrupted() {
return currentThread().isInterrupted(true);
//调用isInterrupted(flag)--有参重载
}
public boolean isInterrupted() {
return isInterrupted(false);
//调用isInterrupted(flag)--有参重载
}
/**
*测试某些线程是否已被中断。中断状态根据传递的ClearInterrupted(即flag)值重置或不重置。
*/
private native boolean isInterrupted(boolean ClearInterrupted);
上面我们从api中了解到,
如果该线程阻塞的调用wait()
, wait(long)
,或wait(long, int)
的方法Object
类,或者在join()
, join(long)
, join(long, int)
, sleep(long)
,或sleep(long, int)
,这个类的方法,那么它的中断状态将被清除,并且将收到一个InterruptedException
。
那么我们来验证一下:
Thread t = new Thread(new Runnable() {
@Override
public void run() {
//打印当前线程是否是中断状态
while (true){
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.interrupted());
}
}
},"t1");
t.start();
t.interrupt();
注意,这里虽然会抛异常但是却没有结束线程,下篇我们将介绍几种结束线程的案例,接下来是wait。
//wait()时调用interrupt()
Thread t = new Thread(new Runnable() {
private final Object o = new Object();
@Override
public void run() {
//打印当前线程是否是中断状态
while (true){
synchronized (o){
try {
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.interrupted());
}
}
},"t1");
t.start();
t.interrupt();
接下来是join,但是上篇我们提到join的底层是wait(),而被wait()的对象是相对于在哪里调用的那个,所以这里我们应该用main线程的interrupt(),如果有对join()不明白的可以去看上篇文章,篇头有直链。
//在join时调用interrupt()
final Thread main = Thread.currentThread();
Thread t = new Thread(new Runnable() {
private final Object o = new Object();
@Override
public void run() {
//打印当前线程是否是中断状态
while (true){
}
}
},"t1");
t.start();
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
main.interrupt();
System.out.println("t interrupt");
}
});
t2.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}