Thread的Interrupt()源代码分析(7)

接上一篇:Thread的join()源代码分析(6)

今天我们来学习下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否则。

另请参见:

isInterrupted()

 

 

public boolean isInterrupted()

测试这个线程是否被中断。 线程的中断状态不受此方法的影响。

忽略线程中断,因为线程在中断时不存在将被该方法返回false所反映。

结果

true如果这个线程已被中断; false否则。

另请参见:

interrupted()

请看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();
}

控制台打印:

Thread的Interrupt()源代码分析(7)

而此时线程还是处于中断状态。说明此方法并不会中断线程,而是赋给了一个中断的状态。

而为什么会有两个判断线程中断状态的方法(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());

Thread的Interrupt()源代码分析(7)

再来看下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());

Thread的Interrupt()源代码分析(7)

我们来看下源码给的解释:

 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();

Thread的Interrupt()源代码分析(7)

注意,这里虽然会抛异常但是却没有结束线程,下篇我们将介绍几种结束线程的案例,接下来是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();

Thread的Interrupt()源代码分析(7)

接下来是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();
		}

Thread的Interrupt()源代码分析(7)